Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3253 lines
82 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. kernlini.c
  5. Abstract:
  6. This module contains the code to initialize the kernel data structures
  7. and to initialize the idle thread, its process, and the processor control
  8. block.
  9. For the i386, it also contains code to initialize the PCR.
  10. Author:
  11. David N. Cutler (davec) 21-Apr-1989
  12. Environment:
  13. Kernel mode only.
  14. Revision History:
  15. 24-Jan-1990 shielin
  16. Changed for NT386
  17. 20-Mar-1990 bryanwi
  18. Added KiInitializePcr
  19. --*/
  20. #include "ki.h"
  21. #include "fastsys.inc"
  22. #define TRAP332_GATE 0xEF00
  23. VOID
  24. KiSetProcessorType(
  25. VOID
  26. );
  27. VOID
  28. KiSetCR0Bits(
  29. VOID
  30. );
  31. BOOLEAN
  32. KiIsNpxPresent(
  33. VOID
  34. );
  35. VOID
  36. KiI386PentiumLockErrataFixup (
  37. VOID
  38. );
  39. VOID
  40. KiInitializeDblFaultTSS(
  41. IN PKTSS Tss,
  42. IN ULONG Stack,
  43. IN PKGDTENTRY TssDescriptor
  44. );
  45. VOID
  46. KiInitializeTSS2 (
  47. IN PKTSS Tss,
  48. IN PKGDTENTRY TssDescriptor
  49. );
  50. VOID
  51. KiSwapIDT (
  52. VOID
  53. );
  54. VOID
  55. KeSetup80387OrEmulate (
  56. IN PVOID *R3EmulatorTable
  57. );
  58. VOID
  59. KiGetCacheInformation(
  60. VOID
  61. );
  62. ULONG
  63. KiGetCpuVendor(
  64. VOID
  65. );
  66. ULONG
  67. KiGetFeatureBits (
  68. VOID
  69. );
  70. NTSTATUS
  71. KiMoveRegTree(
  72. HANDLE Source,
  73. HANDLE Dest
  74. );
  75. VOID
  76. Ki386EnableDE (
  77. IN volatile PLONG Number
  78. );
  79. VOID
  80. Ki386EnableFxsr (
  81. IN volatile PLONG Number
  82. );
  83. VOID
  84. Ki386EnableXMMIExceptions (
  85. IN volatile PLONG Number
  86. );
  87. VOID
  88. Ki386EnableGlobalPage (
  89. IN volatile PLONG Number
  90. );
  91. VOID
  92. Ki386UseSynchronousTbFlush (
  93. IN volatile PLONG Number
  94. );
  95. BOOLEAN
  96. KiInitMachineDependent (
  97. VOID
  98. );
  99. VOID
  100. KiInitializeMTRR (
  101. IN BOOLEAN LastProcessor
  102. );
  103. VOID
  104. KiInitializePAT (
  105. VOID
  106. );
  107. VOID
  108. KiAmdK6InitializeMTRR(
  109. VOID
  110. );
  111. VOID
  112. KiRestoreFastSyscallReturnState(
  113. VOID
  114. );
  115. VOID
  116. KiLogMcaErrors (
  117. VOID
  118. );
  119. #ifdef ALLOC_PRAGMA
  120. #pragma alloc_text(INIT,KiInitializeKernel)
  121. #pragma alloc_text(INIT,KiInitializePcr)
  122. #pragma alloc_text(INIT,KiInitializeDblFaultTSS)
  123. #pragma alloc_text(INIT,KiInitializeTSS2)
  124. #pragma alloc_text(INIT,KiSwapIDT)
  125. #pragma alloc_text(INIT,KeSetup80387OrEmulate)
  126. #pragma alloc_text(INIT,KiGetFeatureBits)
  127. #pragma alloc_text(INIT,KiGetCacheInformation)
  128. #pragma alloc_text(INIT,KiGetCpuVendor)
  129. #pragma alloc_text(INIT,KiMoveRegTree)
  130. #pragma alloc_text(INIT,KiInitMachineDependent)
  131. #pragma alloc_text(INIT,KiI386PentiumLockErrataFixup)
  132. #pragma alloc_text(INIT,KiLogMcaErrors)
  133. #endif
  134. BOOLEAN KiI386PentiumLockErrataPresent = FALSE;
  135. BOOLEAN KiIgnoreUnexpectedTrap07 = FALSE;
  136. ULONG KiFastSystemCallDisable;
  137. extern PVOID Ki387RoundModeTable;
  138. extern PVOID Ki386IopmSaveArea;
  139. extern ULONG KeI386ForceNpxEmulation;
  140. extern WCHAR CmDisabledFloatingPointProcessor[];
  141. extern UCHAR CmpCyrixID[];
  142. extern UCHAR CmpIntelID[];
  143. extern UCHAR CmpAmdID[];
  144. extern UCHAR CmpTransmetaID[];
  145. extern UCHAR CmpCentaurID[];
  146. extern BOOLEAN KiFastSystemCallIsIA32;
  147. #ifndef NT_UP
  148. extern PVOID ScPatchFxb;
  149. extern PVOID ScPatchFxe;
  150. #endif
  151. typedef enum {
  152. CPU_NONE,
  153. CPU_INTEL,
  154. CPU_AMD,
  155. CPU_CYRIX,
  156. CPU_TRANSMETA,
  157. CPU_CENTAUR,
  158. CPU_UNKNOWN
  159. } CPU_VENDORS;
  160. //
  161. // If this processor does XMMI, take advantage of it. Default is
  162. // no XMMI.
  163. //
  164. BOOLEAN KeI386XMMIPresent;
  165. //
  166. // x86 statically provides the idle process and idle thread for
  167. // processor 0.
  168. //
  169. EPROCESS KiIdleProcess;
  170. ETHREAD KiIdleThread0;
  171. //
  172. // Define prototypes and static initialization for the fast zero
  173. // page routines.
  174. //
  175. VOID
  176. FASTCALL
  177. KiZeroPage (
  178. PVOID PageBase
  179. );
  180. VOID
  181. FASTCALL
  182. KiXMMIZeroPage (
  183. PVOID PageBase
  184. );
  185. VOID
  186. FASTCALL
  187. KiXMMIZeroPageNoSave (
  188. PVOID PageBase
  189. );
  190. KE_ZERO_PAGE_ROUTINE KeZeroPage = KiZeroPage;
  191. KE_ZERO_PAGE_ROUTINE KeZeroPageFromIdleThread = KiZeroPage;
  192. //
  193. // Line size of the d-cache closest to the processor. Used by machine
  194. // dependent prefetch routines. Default to 32.
  195. //
  196. ULONG KePrefetchNTAGranularity = 32;
  197. VOID
  198. FASTCALL
  199. RtlPrefetchMemoryNonTemporal(
  200. PVOID Memory,
  201. SIZE_T Length
  202. );
  203. //
  204. // The following spinlock is for compatiblity with 486 systems that don't
  205. // have a cmpxchg8b instruction and therefore need to synchronize using a
  206. // spinlock. NOTE: This spinlock should be initialized on x86 systems.
  207. //
  208. ULONG Ki486CompatibilityLock;
  209. //
  210. // Profile vars
  211. //
  212. extern KIDTENTRY IDT[];
  213. VOID
  214. KiInitializeKernel (
  215. IN PKPROCESS Process,
  216. IN PKTHREAD Thread,
  217. IN PVOID IdleStack,
  218. IN PKPRCB Prcb,
  219. IN CCHAR Number,
  220. PLOADER_PARAMETER_BLOCK LoaderBlock
  221. )
  222. /*++
  223. Routine Description:
  224. This function gains control after the system has been bootstrapped and
  225. before the system has been initialized. Its function is to initialize
  226. the kernel data structures, initialize the idle thread and process objects,
  227. initialize the processor control block, call the executive initialization
  228. routine, and then return to the system startup routine. This routine is
  229. also called to initialize the processor specific structures when a new
  230. processor is brought on line.
  231. Arguments:
  232. Process - Supplies a pointer to a control object of type process for
  233. the specified processor.
  234. Thread - Supplies a pointer to a dispatcher object of type thread for
  235. the specified processor.
  236. IdleStack - Supplies a pointer the base of the real kernel stack for
  237. idle thread on the specified processor.
  238. Prcb - Supplies a pointer to a processor control block for the specified
  239. processor.
  240. Number - Supplies the number of the processor that is being
  241. initialized.
  242. LoaderBlock - Supplies a pointer to the loader parameter block.
  243. Return Value:
  244. None.
  245. --*/
  246. {
  247. LONG Index;
  248. ULONG DirectoryTableBase[2];
  249. KIRQL OldIrql;
  250. PKPCR Pcr;
  251. BOOLEAN NpxFlag;
  252. BOOLEAN FxsrPresent;
  253. BOOLEAN XMMIPresent;
  254. ULONG FeatureBits;
  255. KiSetProcessorType();
  256. KiSetCR0Bits();
  257. NpxFlag = KiIsNpxPresent();
  258. Pcr = KeGetPcr();
  259. //
  260. // Initialize DPC listhead and lock.
  261. //
  262. InitializeListHead(&Prcb->DpcListHead);
  263. KeInitializeSpinLock(&Prcb->DpcLock);
  264. Prcb->DpcRoutineActive = 0;
  265. Prcb->DpcQueueDepth = 0;
  266. Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
  267. Prcb->MinimumDpcRate = KiMinimumDpcRate;
  268. Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
  269. //
  270. // Initialize processor's PowerState
  271. //
  272. PoInitializePrcb (Prcb);
  273. //
  274. // Check for unsupported processor revision
  275. //
  276. if (Prcb->CpuType == 3) {
  277. KeBugCheckEx(UNSUPPORTED_PROCESSOR,0x386,0,0,0);
  278. }
  279. //
  280. // Get the processor FeatureBits for this processor.
  281. //
  282. FeatureBits = KiGetFeatureBits();
  283. Prcb->FeatureBits = FeatureBits;
  284. //
  285. // Do one time initialization of the ProcesorControlSpace in the PRCB
  286. // so local kernel debugger can get things like the GDT
  287. //
  288. KiSaveProcessorControlState(&Prcb->ProcessorState);
  289. //
  290. // Get processor Cache Size information.
  291. //
  292. KiGetCacheInformation();
  293. //
  294. // initialize the per processor lock queue entry for implemented locks.
  295. //
  296. KiInitQueuedSpinLocks(Prcb, Number);
  297. //
  298. // If the initial processor is being initialized, then initialize the
  299. // per system data structures.
  300. //
  301. if (Number == 0) {
  302. //
  303. // Set default node. Used in non-multinode systems and in
  304. // multinode systems until the node topology is available.
  305. //
  306. KeNodeBlock[0] = &KiNode0;
  307. #if defined(KE_MULTINODE)
  308. for (Index = 1; Index < MAXIMUM_CCNUMA_NODES; Index++) {
  309. //
  310. // Set temporary node.
  311. //
  312. KeNodeBlock[Index] = &KiNodeInit[Index];
  313. }
  314. #endif
  315. Prcb->ParentNode = KeNodeBlock[0];
  316. KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
  317. //
  318. // Initial setting for global Cpu & Stepping levels
  319. //
  320. KeI386NpxPresent = NpxFlag;
  321. KeI386CpuType = Prcb->CpuType;
  322. KeI386CpuStep = Prcb->CpuStep;
  323. KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  324. KeProcessorLevel = (USHORT)Prcb->CpuType;
  325. if (Prcb->CpuID == 0) {
  326. KeProcessorRevision = 0xFF00 |
  327. (((Prcb->CpuStep >> 4) + 0xa0 ) & 0x0F0) |
  328. (Prcb->CpuStep & 0xf);
  329. } else {
  330. KeProcessorRevision = Prcb->CpuStep;
  331. }
  332. KeFeatureBits = FeatureBits;
  333. KeI386FxsrPresent = ((KeFeatureBits & KF_FXSR) ? TRUE:FALSE);
  334. KeI386XMMIPresent = ((KeFeatureBits & KF_XMMI) ? TRUE:FALSE);
  335. //
  336. // As of Whistler, cmpxchg8b is a required instruction.
  337. //
  338. if ((KeFeatureBits & KF_CMPXCHG8B) == 0) {
  339. ULONG Vendor[3];
  340. //
  341. // Argument 1:
  342. // bits 31-24: Unique value for missing feature.
  343. // bits 23-0 : Family/Model/Stepping (this could compress).
  344. // Arguments 2 thru 4:
  345. // Vendor Id string.
  346. //
  347. RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor));
  348. KeBugCheckEx(UNSUPPORTED_PROCESSOR,
  349. (1 << 24 ) // rev this for other required features
  350. | (Prcb->CpuType << 16) | Prcb->CpuStep,
  351. Vendor[0],
  352. Vendor[1],
  353. Vendor[2]
  354. );
  355. }
  356. //
  357. // Lower IRQL to APC level.
  358. //
  359. KeLowerIrql(APC_LEVEL);
  360. //
  361. // Initialize kernel internal spinlocks
  362. //
  363. KeInitializeSpinLock(&KiFreezeExecutionLock);
  364. //
  365. // Initialize 486 compatibility lock
  366. //
  367. KeInitializeSpinLock(&Ki486CompatibilityLock);
  368. #if !defined(NT_UP)
  369. //
  370. // Set this processor as the master (ie first found) processor
  371. // in this SMT set (whether or not it is actually SMT).
  372. //
  373. Prcb->MultiThreadSetMaster = Prcb;
  374. //
  375. // During Text Mode setup, it is possible the system is
  376. // running with an MP kernel and a UP HAL. On X86 systems,
  377. // spinlocks are implemented in both the kernel and the HAL
  378. // with the verisons that alter IRQL in the HAL. If the
  379. // HAL is UP, it will not actually acquire/release locks
  380. // while the MP kernel will which will cause the system to
  381. // hang (or crash). As this can only occur during text
  382. // mode setup, we will detect the situation and disable
  383. // the kernel only versions of queued spinlocks if the HAL
  384. // is UP (and the kernel MP).
  385. //
  386. // We need to patch 3 routines, two of them are void and
  387. // the other returns a boolean (must be true (and ZF must be
  388. // clear) in a UP case).
  389. //
  390. // Determine if the HAL us UP by acquiring the dispatcher
  391. // lock and examining it to see if the HAL actually did
  392. // anything to it.
  393. //
  394. OldIrql = KfAcquireSpinLock(&Ki486CompatibilityLock);
  395. if (Ki486CompatibilityLock == 0) {
  396. //
  397. // KfAcquireSpinLock is in the HAL and it did not
  398. // change the value of the lock. This is a UP HAL.
  399. //
  400. extern UCHAR KeTryToAcquireQueuedSpinLockAtRaisedIrqlUP;
  401. PUCHAR PatchTarget, PatchSource;
  402. UCHAR Byte;
  403. #define RET 0xc3
  404. *(PUCHAR)(KeAcquireQueuedSpinLockAtDpcLevel) = RET;
  405. *(PUCHAR)(KeReleaseQueuedSpinLockFromDpcLevel) = RET;
  406. //
  407. // Copy the UP version of KeTryToAcquireQueuedSpinLockAtRaisedIrql
  408. // over the top of the MP versin.
  409. //
  410. PatchSource = &(KeTryToAcquireQueuedSpinLockAtRaisedIrqlUP);
  411. PatchTarget = (PUCHAR)(KeTryToAcquireQueuedSpinLockAtRaisedIrql);
  412. do {
  413. Byte = *PatchSource++;
  414. *PatchTarget++ = Byte;
  415. } while (Byte != RET);
  416. #undef RET
  417. }
  418. KeReleaseSpinLock(&Ki486CompatibilityLock, OldIrql);
  419. #endif
  420. //
  421. // Performance architecture independent initialization.
  422. //
  423. KiInitSystem();
  424. //
  425. // Initialize idle thread process object and then set:
  426. //
  427. // 1. all the quantum values to the maximum possible.
  428. // 2. the process in the balance set.
  429. // 3. the active processor mask to the specified process.
  430. //
  431. DirectoryTableBase[0] = 0;
  432. DirectoryTableBase[1] = 0;
  433. KeInitializeProcess(Process,
  434. (KPRIORITY)0,
  435. (KAFFINITY)(0xffffffff),
  436. &DirectoryTableBase[0],
  437. FALSE);
  438. Process->ThreadQuantum = MAXCHAR;
  439. #if !defined(NT_UP)
  440. } else {
  441. //
  442. // Adjust global cpu setting to represent lowest of all processors
  443. //
  444. FxsrPresent = ((FeatureBits & KF_FXSR) ? TRUE:FALSE);
  445. if (FxsrPresent != KeI386FxsrPresent) {
  446. //
  447. // FXSR support must be available on all processors or on none
  448. //
  449. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_FXSR, 0, 0, 0);
  450. }
  451. XMMIPresent = ((FeatureBits & KF_XMMI) ? TRUE:FALSE);
  452. if (XMMIPresent != KeI386XMMIPresent) {
  453. //
  454. // XMMI support must be available on all processors or on none
  455. //
  456. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_XMMI, 0, 0, 0);
  457. }
  458. if (NpxFlag != KeI386NpxPresent) {
  459. //
  460. // NPX support must be available on all processors or on none
  461. //
  462. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, 0x387, 0, 0, 0);
  463. }
  464. if ((ULONG)(Prcb->CpuType) != KeI386CpuType) {
  465. if ((ULONG)(Prcb->CpuType) < KeI386CpuType) {
  466. //
  467. // What is the lowest CPU type
  468. //
  469. KeI386CpuType = (ULONG)Prcb->CpuType;
  470. KeProcessorLevel = (USHORT)Prcb->CpuType;
  471. }
  472. }
  473. if ((KiBootFeatureBits & KF_CMPXCHG8B) && !(FeatureBits & KF_CMPXCHG8B)) {
  474. //
  475. // cmpxchg8b must be available on all processors, if installed at boot
  476. //
  477. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_CMPXCHG8B, 0, 0, 0);
  478. }
  479. if ((KeFeatureBits & KF_GLOBAL_PAGE) && !(FeatureBits & KF_GLOBAL_PAGE)) {
  480. //
  481. // Global page support must be available on all processors, if on boot processor
  482. //
  483. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_GLOBAL_PAGE, 0, 0, 0);
  484. }
  485. if ((KeFeatureBits & KF_PAT) && !(FeatureBits & KF_PAT)) {
  486. //
  487. // PAT must be available on all processors, if on boot processor
  488. //
  489. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_PAT, 0, 0, 0);
  490. }
  491. if ((KeFeatureBits & KF_MTRR) && !(FeatureBits & KF_MTRR)) {
  492. //
  493. // MTRR must be available on all processors, if on boot processor
  494. //
  495. KeBugCheckEx (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED, KF_MTRR, 0, 0, 0);
  496. }
  497. if ((KeFeatureBits & KF_FAST_SYSCALL) != (FeatureBits & KF_FAST_SYSCALL)) {
  498. //
  499. // If this feature is not available on all processors
  500. // don't use it at all.
  501. //
  502. KiFastSystemCallDisable = 1;
  503. }
  504. if ((KeFeatureBits & KF_XMMI64) != (FeatureBits & KF_XMMI64)) {
  505. //
  506. // If not all processors support Streaming SIMD Extensions
  507. // 64bit FP don't use it at all.
  508. //
  509. KeFeatureBits &= ~KF_XMMI64;
  510. }
  511. //
  512. // Use lowest stepping value
  513. //
  514. if (Prcb->CpuStep < KeI386CpuStep) {
  515. KeI386CpuStep = Prcb->CpuStep;
  516. if (Prcb->CpuID == 0) {
  517. KeProcessorRevision = 0xFF00 |
  518. ((Prcb->CpuStep >> 8) + 'A') |
  519. (Prcb->CpuStep & 0xf);
  520. } else {
  521. KeProcessorRevision = Prcb->CpuStep;
  522. }
  523. }
  524. //
  525. // Use subset of all NT feature bits available on each processor
  526. //
  527. KeFeatureBits &= FeatureBits;
  528. //
  529. // Lower IRQL to DISPATCH level.
  530. //
  531. KeLowerIrql(DISPATCH_LEVEL);
  532. #endif
  533. }
  534. //
  535. // Update processor features
  536. //
  537. SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
  538. (KeFeatureBits & KF_MMX) ? TRUE : FALSE;
  539. SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
  540. (KeFeatureBits & KF_CMPXCHG8B) ? TRUE : FALSE;
  541. SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
  542. ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI)) ? TRUE : FALSE;
  543. SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
  544. ((KeFeatureBits & KF_FXSR) && (KeFeatureBits & KF_XMMI64)) ? TRUE : FALSE;
  545. SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
  546. (KeFeatureBits & KF_3DNOW) ? TRUE : FALSE;
  547. SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
  548. (KeFeatureBits & KF_RDTSC) ? TRUE : FALSE;
  549. //
  550. // Initialize idle thread object and then set:
  551. //
  552. // 1. the initial kernel stack to the specified idle stack.
  553. // 2. the next processor number to the specified processor.
  554. // 3. the thread priority to the highest possible value.
  555. // 4. the state of the thread to running.
  556. // 5. the thread affinity to the specified processor.
  557. // 6. the specified processor member in the process active processors
  558. // set.
  559. //
  560. KeInitializeThread(Thread, (PVOID)((ULONG)IdleStack),
  561. (PKSYSTEM_ROUTINE)NULL, (PKSTART_ROUTINE)NULL,
  562. (PVOID)NULL, (PCONTEXT)NULL, (PVOID)NULL, Process);
  563. Thread->NextProcessor = Number;
  564. Thread->Priority = HIGH_PRIORITY;
  565. Thread->State = Running;
  566. Thread->Affinity = (KAFFINITY)(1<<Number);
  567. Thread->WaitIrql = DISPATCH_LEVEL;
  568. SetMember(Number, Process->ActiveProcessors);
  569. //
  570. // Initialize the processor block. (Note that some fields have been
  571. // initialized at KiInitializePcr().
  572. //
  573. Prcb->CurrentThread = Thread;
  574. Prcb->NextThread = (PKTHREAD)NULL;
  575. Prcb->IdleThread = Thread;
  576. Pcr->NtTib.StackBase = Thread->InitialStack;
  577. //
  578. // call the executive initialization routine.
  579. //
  580. try {
  581. ExpInitializeExecutive(Number, LoaderBlock);
  582. } except(KeBugCheckEx(PHASE0_EXCEPTION,
  583. (ULONG)GetExceptionCode(),
  584. (ULONG_PTR)GetExceptionInformation(),
  585. 0,0), EXCEPTION_EXECUTE_HANDLER) {
  586. ; // should never get here
  587. }
  588. //
  589. // If the initial processor is being initialized, then compute the
  590. // timer table reciprocal value and reset the PRCB values for the
  591. // controllable DPC behavior in order to reflect any registry
  592. // overrides.
  593. //
  594. if (Number == 0) {
  595. KiTimeIncrementReciprocal = KiComputeReciprocal((LONG)KeMaximumIncrement,
  596. &KiTimeIncrementShiftCount);
  597. Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
  598. Prcb->MinimumDpcRate = KiMinimumDpcRate;
  599. Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
  600. }
  601. if (Number == 0) {
  602. //
  603. // Processor 0's DPC stack was temporarily allocated on
  604. // the Double Fault Stack, switch to a proper kernel
  605. // stack now.
  606. //
  607. PVOID DpcStack;
  608. DpcStack = MmCreateKernelStack(FALSE, 0);
  609. if (DpcStack == NULL) {
  610. KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
  611. }
  612. Prcb->DpcStack = DpcStack;
  613. //
  614. // Allocate 8k IOPM bit map saved area to allow BiosCall swap
  615. // bit maps.
  616. //
  617. Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool,
  618. PAGE_SIZE * 2,
  619. ' eK');
  620. if (Ki386IopmSaveArea == NULL) {
  621. KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0);
  622. }
  623. }
  624. //
  625. // Set the priority of the specified idle thread to zero, set appropriate
  626. // member in KiIdleSummary and return to the system start up routine.
  627. //
  628. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  629. KeSetPriorityThread(Thread, (KPRIORITY)0);
  630. //
  631. // if a thread has not been selected to run on the current processors,
  632. // check to see if there are any ready threads; otherwise add this
  633. // processors to the IdleSummary
  634. //
  635. KeAcquireQueuedSpinLockAtDpcLevel(KeQueuedSpinLockContext(LockQueueDispatcherLock));
  636. if (Prcb->NextThread == (PKTHREAD)NULL) {
  637. SetMember(Number, KiIdleSummary);
  638. }
  639. KeReleaseQueuedSpinLockFromDpcLevel(KeQueuedSpinLockContext(LockQueueDispatcherLock));
  640. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  641. //
  642. // This processor has initialized
  643. //
  644. LoaderBlock->Prcb = (ULONG)NULL;
  645. return;
  646. }
  647. VOID
  648. KiInitializePcr (
  649. IN ULONG Processor,
  650. IN PKPCR Pcr,
  651. IN PKIDTENTRY Idt,
  652. IN PKGDTENTRY Gdt,
  653. IN PKTSS Tss,
  654. IN PKTHREAD Thread,
  655. IN PVOID DpcStack
  656. )
  657. /*++
  658. Routine Description:
  659. This function is called to initialize the PCR for a processor. It
  660. simply stuffs values into the PCR. (The PCR is not inited statically
  661. because the number varies with the number of processors.)
  662. Note that each processor has its own IDT, GDT, and TSS as well as PCR!
  663. Arguments:
  664. Processor - Processor whose PCR to initialize.
  665. Pcr - Linear address of PCR.
  666. Idt - Linear address of i386 IDT.
  667. Gdt - Linear address of i386 GDT.
  668. Tss - Linear address (NOT SELECTOR!) of the i386 TSS.
  669. Thread - Dummy thread object to use very early on.
  670. Return Value:
  671. None.
  672. --*/
  673. {
  674. // set version values
  675. Pcr->MajorVersion = PCR_MAJOR_VERSION;
  676. Pcr->MinorVersion = PCR_MINOR_VERSION;
  677. Pcr->PrcbData.MajorVersion = PRCB_MAJOR_VERSION;
  678. Pcr->PrcbData.MinorVersion = PRCB_MINOR_VERSION;
  679. Pcr->PrcbData.BuildType = 0;
  680. #if DBG
  681. Pcr->PrcbData.BuildType |= PRCB_BUILD_DEBUG;
  682. #endif
  683. #ifdef NT_UP
  684. Pcr->PrcbData.BuildType |= PRCB_BUILD_UNIPROCESSOR;
  685. #endif
  686. #if defined (_X86PAE_)
  687. if (Processor == 0) {
  688. //
  689. // PAE feature must be initialized prior to the first HAL call.
  690. //
  691. SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = TRUE;
  692. }
  693. #endif
  694. // Basic addressing fields
  695. Pcr->SelfPcr = Pcr;
  696. Pcr->Prcb = &(Pcr->PrcbData);
  697. // Thread control fields
  698. Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
  699. Pcr->NtTib.StackBase = 0;
  700. Pcr->NtTib.StackLimit = 0;
  701. Pcr->NtTib.Self = 0;
  702. Pcr->PrcbData.CurrentThread = Thread;
  703. //
  704. // Init Prcb.Number and ProcessorBlock such that Ipi will work
  705. // as early as possible.
  706. //
  707. Pcr->PrcbData.Number = (UCHAR)Processor;
  708. Pcr->PrcbData.SetMember = 1 << Processor;
  709. KiProcessorBlock[Processor] = Pcr->Prcb;
  710. Pcr->Irql = 0;
  711. // Machine structure addresses
  712. Pcr->GDT = Gdt;
  713. Pcr->IDT = Idt;
  714. Pcr->TSS = Tss;
  715. Pcr->PrcbData.DpcStack = DpcStack;
  716. //
  717. // Initially, set this processor as only member of SMT set.
  718. //
  719. Pcr->PrcbData.MultiThreadProcessorSet = Pcr->PrcbData.SetMember;
  720. return;
  721. }
  722. #if 0
  723. VOID
  724. KiInitializeDblFaultTSS(
  725. IN PKTSS Tss,
  726. IN ULONG Stack,
  727. IN PKGDTENTRY TssDescriptor
  728. )
  729. /*++
  730. Routine Description:
  731. This function is called to initialize the double-fault TSS for a
  732. processor. It will set the static fields of the TSS to point to
  733. the double-fault handler and the appropriate double-fault stack.
  734. Note that the IOPM for the double-fault TSS grants access to all
  735. ports. This is so the standard HAL's V86-mode callback to reset
  736. the display to text mode will work.
  737. Arguments:
  738. Tss - Supplies a pointer to the double-fault TSS
  739. Stack - Supplies a pointer to the double-fault stack.
  740. TssDescriptor - Linear address of the descriptor for the TSS.
  741. Return Value:
  742. None.
  743. --*/
  744. {
  745. PUCHAR p;
  746. ULONG i;
  747. ULONG j;
  748. //
  749. // Set limit for TSS
  750. //
  751. if (TssDescriptor != NULL) {
  752. TssDescriptor->LimitLow = sizeof(KTSS) - 1;
  753. TssDescriptor->HighWord.Bits.LimitHi = 0;
  754. }
  755. //
  756. // Initialize IOPMs
  757. //
  758. for (i = 0; i < IOPM_COUNT; i++) {
  759. p = (PUCHAR)(Tss->IoMaps[i]);
  760. for (j = 0; j < PIOPM_SIZE; j++) {
  761. p[j] = 0;
  762. }
  763. }
  764. // Set IO Map base address to indicate no IO map present.
  765. // N.B. -1 does not seem to be a valid value for the map base. If this
  766. // value is used, byte immediate in's and out's will actually go
  767. // the hardware when executed in V86 mode.
  768. Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
  769. // Set flags to 0, which in particular disables traps on task switches.
  770. Tss->Flags = 0;
  771. // Set LDT and Ss0 to constants used by NT.
  772. Tss->LDT = 0;
  773. Tss->Ss0 = KGDT_R0_DATA;
  774. Tss->Esp0 = Stack;
  775. Tss->Eip = (ULONG)KiTrap08;
  776. Tss->Cs = KGDT_R0_CODE || RPL_MASK;
  777. Tss->Ds = KGDT_R0_DATA;
  778. Tss->Es = KGDT_R0_DATA;
  779. Tss->Fs = KGDT_R0_DATA;
  780. return;
  781. }
  782. #endif
  783. VOID
  784. KiInitializeTSS (
  785. IN PKTSS Tss
  786. )
  787. /*++
  788. Routine Description:
  789. This function is called to initialize the TSS for a processor.
  790. It will set the static fields of the TSS. (ie Those fields that
  791. the part reads, and for which NT uses constant values.)
  792. The dynamic fields (Esp0 and CR3) are set in the context swap
  793. code.
  794. Arguments:
  795. Tss - Linear address of the Task State Segment.
  796. Return Value:
  797. None.
  798. --*/
  799. {
  800. // Set IO Map base address to indicate no IO map present.
  801. // N.B. -1 does not seem to be a valid value for the map base. If this
  802. // value is used, byte immediate in's and out's will actually go
  803. // the hardware when executed in V86 mode.
  804. Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
  805. // Set flags to 0, which in particular disables traps on task switches.
  806. Tss->Flags = 0;
  807. // Set LDT and Ss0 to constants used by NT.
  808. Tss->LDT = 0;
  809. Tss->Ss0 = KGDT_R0_DATA;
  810. return;
  811. }
  812. VOID
  813. KiInitializeTSS2 (
  814. IN PKTSS Tss,
  815. IN PKGDTENTRY TssDescriptor
  816. )
  817. /*++
  818. Routine Description:
  819. Do part of TSS init we do only once.
  820. Arguments:
  821. Tss - Linear address of the Task State Segment.
  822. TssDescriptor - Linear address of the descriptor for the TSS.
  823. Return Value:
  824. None.
  825. --*/
  826. {
  827. PUCHAR p;
  828. ULONG i;
  829. ULONG j;
  830. //
  831. // Set limit for TSS
  832. //
  833. if (TssDescriptor != NULL) {
  834. TssDescriptor->LimitLow = sizeof(KTSS) - 1;
  835. TssDescriptor->HighWord.Bits.LimitHi = 0;
  836. }
  837. //
  838. // Initialize IOPMs
  839. //
  840. for (i = 0; i < IOPM_COUNT; i++) {
  841. p = (PUCHAR)(Tss->IoMaps[i].IoMap);
  842. for (j = 0; j < PIOPM_SIZE; j++) {
  843. p[j] = (UCHAR)-1;
  844. }
  845. }
  846. //
  847. // Initialize Software Interrupt Direction Maps
  848. //
  849. for (i = 0; i < IOPM_COUNT; i++) {
  850. p = (PUCHAR)(Tss->IoMaps[i].DirectionMap);
  851. for (j = 0; j < INT_DIRECTION_MAP_SIZE; j++) {
  852. p[j] = 0;
  853. }
  854. // dpmi requires special case for int 2, 1b, 1c, 23, 24
  855. p[0] = 4;
  856. p[3] = 0x18;
  857. p[4] = 0x18;
  858. }
  859. //
  860. // Initialize the map for IO_ACCESS_MAP_NONE
  861. //
  862. p = (PUCHAR)(Tss->IntDirectionMap);
  863. for (j = 0; j < INT_DIRECTION_MAP_SIZE; j++) {
  864. p[j] = 0;
  865. }
  866. // dpmi requires special case for int 2, 1b, 1c, 23, 24
  867. p[0] = 4;
  868. p[3] = 0x18;
  869. p[4] = 0x18;
  870. return;
  871. }
  872. VOID
  873. KiSwapIDT (
  874. )
  875. /*++
  876. Routine Description:
  877. This function is called to edit the IDT. It swaps words of the address
  878. and access fields around into the format the part actually needs.
  879. This allows for easy static init of the IDT.
  880. Note that this procedure edits the current IDT.
  881. Arguments:
  882. None.
  883. Return Value:
  884. None.
  885. --*/
  886. {
  887. LONG Index;
  888. USHORT Temp;
  889. //
  890. // Rearrange the entries of IDT to match i386 interrupt gate structure
  891. //
  892. for (Index = 0; Index <= MAXIMUM_IDTVECTOR; Index += 1) {
  893. Temp = IDT[Index].Selector;
  894. IDT[Index].Selector = IDT[Index].ExtendedOffset;
  895. IDT[Index].ExtendedOffset = Temp;
  896. }
  897. }
  898. ULONG
  899. KiGetCpuVendor(
  900. VOID
  901. )
  902. /*++
  903. Routine Description:
  904. (Try to) Determine the manufacturer of this processor based on
  905. data returned by the CPUID instruction (if present).
  906. Arguments:
  907. None.
  908. Return Value:
  909. One of the members of the enumeration CPU_VENDORS (defined above).
  910. --*/
  911. {
  912. PKPRCB Prcb;
  913. ULONG Junk;
  914. ULONG Buffer[4];
  915. Prcb = KeGetCurrentPrcb();
  916. Prcb->VendorString[0] = 0;
  917. if (!Prcb->CpuID) {
  918. return CPU_NONE;
  919. }
  920. CPUID(0, &Junk, Buffer+0, Buffer+2, Buffer+1);
  921. Buffer[3] = 0;
  922. //
  923. // Copy vendor string to Prcb for debugging (ensure it's NULL
  924. // terminated).
  925. //
  926. RtlCopyMemory(
  927. Prcb->VendorString,
  928. Buffer,
  929. sizeof(Prcb->VendorString) - 1
  930. );
  931. Prcb->VendorString[sizeof(Prcb->VendorString) - 1] = '\0';
  932. if (strcmp((PVOID)Buffer, CmpIntelID) == 0) {
  933. return CPU_INTEL;
  934. } else if (strcmp((PVOID)Buffer, CmpAmdID) == 0) {
  935. return CPU_AMD;
  936. } else if (strcmp((PVOID)Buffer, CmpCyrixID) == 0) {
  937. return CPU_CYRIX;
  938. } else if (strcmp((PVOID)Buffer, CmpTransmetaID) == 0) {
  939. return CPU_TRANSMETA;
  940. } else if (strcmp((PVOID)Buffer, CmpCentaurID) == 0) {
  941. return CPU_CENTAUR;
  942. }
  943. return CPU_UNKNOWN;
  944. }
  945. ULONG
  946. KiGetFeatureBits (
  947. VOID
  948. )
  949. /*++
  950. Routine Description:
  951. Examine the processor specific feature bits to determine the
  952. Windows 2000 supported features supported by this processor.
  953. Arguments:
  954. None.
  955. Return Value:
  956. Returns a Windows 2000 normalized set of processor features.
  957. --*/
  958. {
  959. ULONG Junk;
  960. ULONG Temp;
  961. ULONG ProcessorFeatures;
  962. ULONG NtBits;
  963. ULONG ExtendedProcessorFeatures;
  964. ULONG ProcessorSignature;
  965. ULONG CpuVendor;
  966. PKPRCB Prcb;
  967. BOOLEAN ExtendedCPUIDSupport = TRUE;
  968. Prcb = KeGetCurrentPrcb();
  969. NtBits = KF_WORKING_PTE;
  970. //
  971. // Determine the processor type
  972. //
  973. CpuVendor = KiGetCpuVendor();
  974. //
  975. // If this processor does not support the CPUID instruction,
  976. // don't try to use it.
  977. //
  978. if (CpuVendor == CPU_NONE) {
  979. return NtBits;
  980. }
  981. //
  982. // Determine which NT compatible features are present
  983. //
  984. CPUID (1, &ProcessorSignature, &Temp, &Junk, &ProcessorFeatures);
  985. //
  986. // CPUID(1) now returns information in EBX. On the grounds that
  987. // the low functions are supposed to be standard, we record the
  988. // information regardless of processor vendor even though it may
  989. // be 0 or undefined on older implementations.
  990. //
  991. Prcb->InitialApicId = (UCHAR)(Temp >> 24);
  992. //
  993. // AMD specific stuff
  994. //
  995. if (CpuVendor == CPU_AMD) {
  996. //
  997. // Check for K5 and above.
  998. //
  999. if ((ProcessorSignature & 0x0F00) >= 0x0500) {
  1000. if ((ProcessorSignature & 0x0F00) == 0x0500) {
  1001. switch (ProcessorSignature & 0x00F0) {
  1002. case 0x0010: // K5 Model 1
  1003. //
  1004. // for K5 Model 1 stepping 0 or 1 don't set global page
  1005. //
  1006. if ((ProcessorSignature & 0x000F) > 0x03) {
  1007. //
  1008. // K5 Model 1 stepping 2 or greater
  1009. //
  1010. break;
  1011. }
  1012. //
  1013. // K5 Model 1 stepping 0 or 1, FALL THRU.
  1014. //
  1015. case 0x0000: // K5 Model 0
  1016. //
  1017. // for K5 Model 0 or model unknown don't set global page
  1018. //
  1019. ProcessorFeatures &= ~0x2000;
  1020. break;
  1021. case 0x0080: // K6 Model 8 (K6-2)
  1022. //
  1023. // All steppings >= 8 support MTRRs.
  1024. //
  1025. if ((ProcessorSignature & 0x000F) >= 0x8) {
  1026. NtBits |= KF_AMDK6MTRR;
  1027. }
  1028. break;
  1029. case 0x0090: // K6 Model 9 (K6-3)
  1030. NtBits |= KF_AMDK6MTRR;
  1031. break;
  1032. default: // anything else, nothing to do.
  1033. break;
  1034. }
  1035. }
  1036. } else {
  1037. //
  1038. // Less than family 5, don't set GLOBAL PAGE, LARGE
  1039. // PAGE or CMOV. (greater than family 5 will have the
  1040. // bits set correctly).
  1041. //
  1042. ProcessorFeatures &= ~(0x08 | 0x2000 | 0x8000);
  1043. //
  1044. // We don't know what this processor returns if we
  1045. // probe for extended CPUID support.
  1046. //
  1047. ExtendedCPUIDSupport = FALSE;
  1048. }
  1049. }
  1050. //
  1051. // Intel specific stuff
  1052. //
  1053. if (CpuVendor == CPU_INTEL) {
  1054. if (Prcb->CpuType >= 6) {
  1055. WRMSR (0x8B, 0);
  1056. CPUID (1, &Junk, &Junk, &Junk, &ProcessorFeatures);
  1057. Prcb->UpdateSignature.QuadPart = RDMSR (0x8B);
  1058. }
  1059. else if (Prcb->CpuType == 5) {
  1060. KiI386PentiumLockErrataPresent = TRUE;
  1061. }
  1062. if ( ((ProcessorSignature & 0x0FF0) == 0x0610 &&
  1063. (ProcessorSignature & 0x000F) <= 0x9) ||
  1064. ((ProcessorSignature & 0x0FF0) == 0x0630 &&
  1065. (ProcessorSignature & 0x000F) <= 0x4)) {
  1066. NtBits &= ~KF_WORKING_PTE;
  1067. }
  1068. //
  1069. // Don't support prior attempts at implementing syscall/sysexit
  1070. // instructions.
  1071. //
  1072. if ((Prcb->CpuType < 6) ||
  1073. ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303))) {
  1074. ProcessorFeatures &= ~KI_FAST_SYSCALL_SUPPORTED;
  1075. }
  1076. }
  1077. //
  1078. // Cyrix specific stuff
  1079. //
  1080. if (CpuVendor == CPU_CYRIX) {
  1081. //
  1082. // Workaround bug 324467 which is caused by INTR being
  1083. // held high too long during an FP instruction and causing
  1084. // random Trap07 with no exception bits.
  1085. //
  1086. extern BOOLEAN KiIgnoreUnexpectedTrap07;
  1087. KiIgnoreUnexpectedTrap07 = TRUE;
  1088. //
  1089. // Workaround CMPXCHG bug to Cyrix processors where
  1090. // Family = 6, Model = 0, Stepping <= 1. Note that
  1091. // Prcb->CpuStep contains both model and stepping.
  1092. //
  1093. // Disable Locking in one of processor specific registers
  1094. // (accessible via i/o space index/data pair).
  1095. //
  1096. if ((Prcb->CpuType == 6) &&
  1097. (Prcb->CpuStep <= 1)) {
  1098. #define CRC_NDX (PUCHAR)0x22
  1099. #define CRC_DAT (CRC_NDX + 1)
  1100. #define CCR1 0xc1
  1101. UCHAR ValueCCR1;
  1102. //
  1103. // Get current setting.
  1104. //
  1105. WRITE_PORT_UCHAR(CRC_NDX, CCR1);
  1106. ValueCCR1 = READ_PORT_UCHAR(CRC_DAT);
  1107. //
  1108. // Set the NO_LOCK bit and write it back.
  1109. //
  1110. ValueCCR1 |= 0x10;
  1111. WRITE_PORT_UCHAR(CRC_NDX, CCR1);
  1112. WRITE_PORT_UCHAR(CRC_DAT, ValueCCR1);
  1113. #undef CCR1
  1114. #undef CRC_DAT
  1115. #undef CRC_NDX
  1116. }
  1117. }
  1118. //
  1119. // Check the standard CPUID feature bits.
  1120. //
  1121. // The following bits are known to work on Intel, AMD and Cyrix.
  1122. // We hope (and assume) the clone makers will follow suit.
  1123. //
  1124. if (ProcessorFeatures & 0x00000002) {
  1125. NtBits |= KF_V86_VIS | KF_CR4;
  1126. }
  1127. if (ProcessorFeatures & 0x00000008) {
  1128. NtBits |= KF_LARGE_PAGE | KF_CR4;
  1129. }
  1130. if (ProcessorFeatures & 0x00000010) {
  1131. NtBits |= KF_RDTSC;
  1132. }
  1133. //
  1134. // N.B. CMPXCHG8B MUST be done in a generic manner or clone processors
  1135. // will not be able to boot if they set this feature bit.
  1136. //
  1137. // This was incorrect in NT4 and resulted processor vendors claiming
  1138. // not to support cmpxchg8b even if they did. Whistler requires
  1139. // cmpxchg8b, work around this problems for the cases we know about.
  1140. //
  1141. // Because cmpxchg8b is a requirement for whistler, winnt32 needs to
  1142. // be modified if new processors are added to the following list.
  1143. // Also, setupldr. Both executables were modified so as to warn
  1144. // the user rather than installing an unbootable system.
  1145. //
  1146. if ((ProcessorFeatures & 0x00000100) == 0) {
  1147. ULONGLONG MsrValue;
  1148. if ((CpuVendor == CPU_TRANSMETA) &&
  1149. (Prcb->CpuType >= 5) &&
  1150. (Prcb->CpuStep >= 0x402)) {
  1151. //
  1152. // Transmeta processors have a cpuid feature bit 'mask' in
  1153. // msr 80860004. Unmask the cmpxchg8b bit.
  1154. //
  1155. MsrValue = RDMSR(0x80860004);
  1156. MsrValue |= 0x100;
  1157. WRMSR(0x80860004, MsrValue);
  1158. ProcessorFeatures |= 0x100;
  1159. } else if ((CpuVendor == CPU_CENTAUR) &&
  1160. (Prcb->CpuType >= 5)) {
  1161. //
  1162. // Centaur/IDT processors turn on the cmpxchg8b
  1163. // feature bit by setting bit 1 in MSR 107.
  1164. //
  1165. ULONG CentaurFeatureControlMSR = 0x107;
  1166. if (Prcb->CpuType >= 6) {
  1167. //
  1168. // Centaur processors (Cyrix III) turn on the cmpxchg8b
  1169. // feature bit by setting bit 1 in MSR 1107.
  1170. //
  1171. CentaurFeatureControlMSR = 0x1107;
  1172. }
  1173. MsrValue = RDMSR(CentaurFeatureControlMSR);
  1174. MsrValue |= 2;
  1175. WRMSR(CentaurFeatureControlMSR, MsrValue);
  1176. ProcessorFeatures |= 0x100;
  1177. }
  1178. }
  1179. if (ProcessorFeatures & 0x00000100) {
  1180. NtBits |= KF_CMPXCHG8B;
  1181. }
  1182. if (ProcessorFeatures & KI_FAST_SYSCALL_SUPPORTED) {
  1183. NtBits |= KF_FAST_SYSCALL;
  1184. KiFastSystemCallIsIA32 = TRUE;
  1185. }
  1186. if (ProcessorFeatures & 0x00001000) {
  1187. NtBits |= KF_MTRR;
  1188. }
  1189. if (ProcessorFeatures & 0x00002000) {
  1190. NtBits |= KF_GLOBAL_PAGE | KF_CR4;
  1191. }
  1192. if (ProcessorFeatures & 0x00008000) {
  1193. NtBits |= KF_CMOV;
  1194. }
  1195. if (ProcessorFeatures & 0x00010000) {
  1196. NtBits |= KF_PAT;
  1197. }
  1198. if (ProcessorFeatures & 0x00200000) {
  1199. NtBits |= KF_DTS;
  1200. }
  1201. if (ProcessorFeatures & 0x00800000) {
  1202. NtBits |= KF_MMX;
  1203. }
  1204. if (ProcessorFeatures & 0x01000000) {
  1205. NtBits |= KF_FXSR;
  1206. }
  1207. if (ProcessorFeatures & 0x02000000) {
  1208. NtBits |= KF_XMMI;
  1209. }
  1210. if (ProcessorFeatures & 0x04000000) {
  1211. NtBits |= KF_XMMI64;
  1212. }
  1213. if (ProcessorFeatures & 0x10000000) {
  1214. NtBits |= KF_SMT;
  1215. Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Temp >> 16);
  1216. } else {
  1217. Prcb->LogicalProcessorsPerPhysicalProcessor = 1;
  1218. }
  1219. //
  1220. // Check extended functions. First, check for existance,
  1221. // then check extended function 0x80000001 (Extended Processor
  1222. // Features) if present.
  1223. //
  1224. // Note: Intel guarantees that no processor that doesn't support
  1225. // extended CPUID functions will ever return a value with the
  1226. // most significant bit set. Microsoft asks all CPU vendors
  1227. // to make the same guarantee.
  1228. //
  1229. if (ExtendedCPUIDSupport != FALSE) {
  1230. CPUID(0x80000000, &Temp, &Junk, &Junk, &Junk);
  1231. //
  1232. // Sanity check the result, assuming there are no more
  1233. // than 256 extended feature functions (should be valid
  1234. // for a little while).
  1235. //
  1236. if ((Temp & 0xffffff00) == 0x80000000) {
  1237. //
  1238. // Check extended processor features. These, by definition,
  1239. // can vary on a processor by processor basis.
  1240. //
  1241. if (Temp >= 0x80000001) {
  1242. CPUID(0x80000001, &Temp, &Junk, &Junk, &ExtendedProcessorFeatures);
  1243. //
  1244. // With these, we can only do what we're told.
  1245. //
  1246. switch (CpuVendor) {
  1247. case CPU_AMD:
  1248. if (ExtendedProcessorFeatures & 0x80000000) {
  1249. NtBits |= KF_3DNOW;
  1250. }
  1251. #if 0
  1252. //
  1253. // There is a security hole with this implementation
  1254. // of fast system call such that it is possible to
  1255. // end up in the trap01 handler running on the user
  1256. // stack (ie not kernel stack). Unfortunately this
  1257. // prohibits use of this instruction pair.
  1258. //
  1259. if (ExtendedProcessorFeatures & 0x00000800) {
  1260. //
  1261. // This processor supports AMD's implementation
  1262. // of SYSENTER/SYSEXIT (SYSCALL/SYSRET). Use this
  1263. // unless it also supports the IA32 version.
  1264. //
  1265. if ((NtBits & KF_FAST_SYSCALL) == 0) {
  1266. NtBits |= KF_FAST_SYSCALL;
  1267. }
  1268. }
  1269. #endif
  1270. #if 0
  1271. if (ExtendedProcessorFeatures & 0x00100000) {
  1272. Temp = (ULONG)RDMSR(0xc0000080);
  1273. Temp |= 0x800;
  1274. WRMSR(0xc0000080, (ULONGLONG)Temp);
  1275. KeErrorMask = 0x9;
  1276. MmPaeErrMask = 0x8;
  1277. MmPaeMask = 0x8000000000000000UI64;
  1278. }
  1279. #endif
  1280. break;
  1281. }
  1282. }
  1283. }
  1284. }
  1285. return NtBits;
  1286. }
  1287. VOID
  1288. KiGetCacheInformation(
  1289. VOID
  1290. )
  1291. {
  1292. #define CPUID_REG_COUNT 4
  1293. ULONG CpuidData[CPUID_REG_COUNT];
  1294. ULONG Line = 64;
  1295. ULONG Size = 0;
  1296. ULONG AdjustedSize = 0;
  1297. UCHAR Assoc = 0;
  1298. ULONG CpuVendor;
  1299. PKPCR Pcr;
  1300. //
  1301. // Set default.
  1302. //
  1303. Pcr = KeGetPcr();
  1304. Pcr->SecondLevelCacheSize = 0;
  1305. //
  1306. // Determine the processor manufacturer
  1307. //
  1308. CpuVendor = KiGetCpuVendor();
  1309. if (CpuVendor == CPU_NONE) {
  1310. return;
  1311. }
  1312. //
  1313. // Obtain Cache size information for those processors on which
  1314. // we know how.
  1315. //
  1316. switch (CpuVendor) {
  1317. case CPU_INTEL:
  1318. CPUID(0, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1319. //
  1320. // Check this processor supports CPUID function 2 which is the
  1321. // one that returns cache size info.
  1322. //
  1323. if (CpuidData[0] >= 2) {
  1324. //
  1325. // The above returns a series of bytes. (In EAX, EBX, ECX
  1326. // and EDX). The least significant byte (of EAX) gives the
  1327. // number of times CPUID(2 ...) should be issued to return
  1328. // the complete set of data. The bytes are self describing
  1329. // data.
  1330. //
  1331. // In particular, the bytes describing the L2 cache size
  1332. // will be in the following set (and meaning)
  1333. //
  1334. // 0x40 0 bytes
  1335. // 0x41 128K bytes
  1336. // 0x42 256K bytes
  1337. // 0x43 512K bytes
  1338. // 0x44 1024K bytes
  1339. // 0x45 2048K bytes
  1340. // 0x46 4096K bytes
  1341. //
  1342. // I am extrapolating the above as anything in the range
  1343. // 0x41 thru 0x4f can be computed as
  1344. //
  1345. // 128KB << (descriptor - 0x41)
  1346. //
  1347. // The Intel folks say keep it to a reasonable upper bound,
  1348. // eg 49.
  1349. //
  1350. // N.B. the range 0x80 .. 0x86 indicates the same cache
  1351. // sizes but 8 way associative.
  1352. //
  1353. // Also, the most significant bit of each register indicates
  1354. // whether not the register contains valid information.
  1355. // 0 == Valid, 1 == InValid.
  1356. //
  1357. ULONG CpuidIterations;
  1358. ULONG i;
  1359. ULONG CpuidReg;
  1360. BOOLEAN FirstPass = TRUE;
  1361. do {
  1362. CPUID(2, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1363. if (FirstPass) {
  1364. //
  1365. // Get the iteration count from the first byte
  1366. // of the returned data then replace that byte
  1367. // with 0 (a null descriptor).
  1368. //
  1369. CpuidIterations = CpuidData[0] & 0xff;
  1370. CpuidData[0] &= 0xffffff00;
  1371. FirstPass = FALSE;
  1372. }
  1373. for (i = 0; i < CPUID_REG_COUNT; i++) {
  1374. CpuidReg = CpuidData[i];
  1375. if (CpuidReg & 0x80000000) {
  1376. //
  1377. // Register doesn't contain valid data,
  1378. // skip it.
  1379. //
  1380. continue;
  1381. }
  1382. while (CpuidReg) {
  1383. //
  1384. // Get LS Byte from this DWORD and remove the
  1385. // byte.
  1386. //
  1387. UCHAR Descriptor = (UCHAR)(CpuidReg & 0xff);
  1388. CpuidReg >>= 8;
  1389. if (Descriptor == 0) {
  1390. //
  1391. // NULL descriptor
  1392. //
  1393. continue;
  1394. }
  1395. if (((Descriptor > 0x40) && (Descriptor <= 0x47)) ||
  1396. ((Descriptor > 0x78) && (Descriptor <= 0x7c)) ||
  1397. ((Descriptor > 0x80) && (Descriptor <= 0x87))) {
  1398. //
  1399. // L2 descriptor.
  1400. //
  1401. // To date, for all the descriptors we know
  1402. // about those above 0x78 are 8 way and those
  1403. // below are 4 way.
  1404. //
  1405. Assoc = Descriptor >= 0x79 ? 8 : 4;
  1406. if (((Descriptor & 0xf8) == 0x78) &&
  1407. (Line < 128)) {
  1408. Line = 128;
  1409. }
  1410. Descriptor &= 0x07;
  1411. //
  1412. // Assert the descriptor is in the range we
  1413. // officially know about. If this hits on
  1414. // a checked build, check with Intel about
  1415. // the interpretation.
  1416. //
  1417. ASSERT(Descriptor <= 0x6);
  1418. Size = 0x10000 << Descriptor;
  1419. if ((Size / Assoc) > AdjustedSize) {
  1420. AdjustedSize = Size / Assoc;
  1421. Pcr->SecondLevelCacheSize = Size;
  1422. Pcr->SecondLevelCacheAssociativity = Assoc;
  1423. }
  1424. } else if ((Descriptor > 0x21) && (Descriptor <= 0x29)) {
  1425. if (Line < 128) {
  1426. Line = 128;
  1427. }
  1428. Assoc = 8;
  1429. switch (Descriptor) {
  1430. case 0x22:
  1431. Size = 512 * 1024;
  1432. Assoc = 4;
  1433. break;
  1434. case 0x23:
  1435. Size = 1024 * 1024;
  1436. break;
  1437. case 0x25:
  1438. Size = 2048 * 1024;
  1439. break;
  1440. case 0x29:
  1441. Size = 4096 * 1024;
  1442. break;
  1443. default:
  1444. Size = 0;
  1445. break;
  1446. }
  1447. if ((Size / Assoc) > AdjustedSize) {
  1448. AdjustedSize = Size / Assoc;
  1449. Pcr->SecondLevelCacheSize = Size;
  1450. Pcr->SecondLevelCacheAssociativity = Assoc;
  1451. }
  1452. } else if ((Descriptor > 0x65) && (Descriptor < 0x69)) {
  1453. //
  1454. // L1 Descriptor with line size of 64 bytes.
  1455. // N.B. These are the only ones we know about,
  1456. // we will get it wrong on future processors
  1457. // unless a less brain dead way of determining
  1458. // line size is provided.
  1459. //
  1460. KePrefetchNTAGranularity = 64;
  1461. }
  1462. //
  1463. // else if (do other descriptors)
  1464. //
  1465. } // while more bytes in this register
  1466. } // for each register
  1467. //
  1468. // Note: Always run thru all iterations indicated by
  1469. // the first to ensure a subsequent call won't start
  1470. // part way thru.
  1471. //
  1472. } while (--CpuidIterations);
  1473. }
  1474. break;
  1475. case CPU_AMD:
  1476. //
  1477. // Get L1 Cache Data.
  1478. //
  1479. CPUID(0x80000000, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1480. if (CpuidData[0] < 0x80000005) {
  1481. //
  1482. // This processor doesn't support L1 cache details.
  1483. //
  1484. break;
  1485. }
  1486. CPUID(0x80000005, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1487. KePrefetchNTAGranularity = CpuidData[2] & 0xff;
  1488. //
  1489. // Get L2 data.
  1490. //
  1491. CPUID(0x80000000, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1492. if (CpuidData[0] < 0x80000006) {
  1493. //
  1494. // This processor doesn't support L2 cache details.
  1495. //
  1496. break;
  1497. }
  1498. CPUID(0x80000006, CpuidData, CpuidData+1, CpuidData+2, CpuidData+3);
  1499. Line = CpuidData[2] & 0xff;
  1500. switch ((CpuidData[2] >> 12) & 0xf) {
  1501. case 0x2: Assoc = 2; break;
  1502. case 0x4: Assoc = 4; break;
  1503. case 0x6: Assoc = 8; break;
  1504. case 0x8: Assoc = 16; break;
  1505. //
  1506. // ff is really fully associative, just represent as 16 way.
  1507. //
  1508. case 0xff: Assoc = 16; break;
  1509. default: Assoc = 1; break;
  1510. }
  1511. Size = (CpuidData[2] >> 16) << 10;
  1512. if ((Pcr->PrcbData.CpuType == 0x6) &&
  1513. (Pcr->PrcbData.CpuStep == 0x300)) {
  1514. //
  1515. // Model 6,3,0 uses a different algorithm to report cache
  1516. // size.
  1517. //
  1518. Size = 64 * 1024;
  1519. }
  1520. Pcr->SecondLevelCacheAssociativity = Assoc;
  1521. Pcr->SecondLevelCacheSize = Size;
  1522. break;
  1523. }
  1524. if (Line > KeLargestCacheLine) {
  1525. KeLargestCacheLine = Line;
  1526. }
  1527. #undef CPUID_REG_COUNT
  1528. }
  1529. #define MAX_ATTEMPTS 10
  1530. BOOLEAN
  1531. KiInitMachineDependent (
  1532. VOID
  1533. )
  1534. {
  1535. KAFFINITY ActiveProcessors, CurrentAffinity;
  1536. ULONG NumberProcessors;
  1537. IDENTITY_MAP IdentityMap;
  1538. ULONG Index;
  1539. ULONG Average;
  1540. ULONG Junk;
  1541. struct {
  1542. LARGE_INTEGER PerfStart;
  1543. LARGE_INTEGER PerfEnd;
  1544. LONGLONG PerfDelta;
  1545. LARGE_INTEGER PerfFreq;
  1546. LONGLONG TSCStart;
  1547. LONGLONG TSCEnd;
  1548. LONGLONG TSCDelta;
  1549. ULONG MHz;
  1550. } Samples[MAX_ATTEMPTS], *pSamp;
  1551. PUCHAR PatchLocation;
  1552. //
  1553. // If PDE large page is supported, enable it.
  1554. //
  1555. // We enable large pages before global pages to make TLB invalidation
  1556. // easier while turning on large pages.
  1557. //
  1558. if (KeFeatureBits & KF_LARGE_PAGE) {
  1559. if (Ki386CreateIdentityMap(&IdentityMap,
  1560. &Ki386EnableCurrentLargePage,
  1561. &Ki386EnableCurrentLargePageEnd )) {
  1562. KiIpiGenericCall (
  1563. (PKIPI_BROADCAST_WORKER) Ki386EnableTargetLargePage,
  1564. (ULONG)(&IdentityMap)
  1565. );
  1566. }
  1567. //
  1568. // Always call Ki386ClearIdentityMap() to free any memory allocated
  1569. //
  1570. Ki386ClearIdentityMap(&IdentityMap);
  1571. }
  1572. //
  1573. // If PDE/PTE global page is supported, enable it
  1574. //
  1575. if (KeFeatureBits & KF_GLOBAL_PAGE) {
  1576. NumberProcessors = KeNumberProcessors;
  1577. KiIpiGenericCall (
  1578. (PKIPI_BROADCAST_WORKER) Ki386EnableGlobalPage,
  1579. (ULONG)(&NumberProcessors)
  1580. );
  1581. }
  1582. #if !defined(NT_UP)
  1583. //
  1584. // If some processor doesn't have proper MP PTE implementation,
  1585. // then use a synchronous TB shoot down handler
  1586. //
  1587. if (!(KeFeatureBits & KF_WORKING_PTE)) {
  1588. NumberProcessors = KeNumberProcessors;
  1589. KiIpiGenericCall (
  1590. (PKIPI_BROADCAST_WORKER) Ki386UseSynchronousTbFlush,
  1591. (ULONG)(&NumberProcessors)
  1592. );
  1593. }
  1594. #endif
  1595. //
  1596. // If PAT or MTRR supported but the HAL indicates it shouldn't
  1597. // be used (eg on a Shared Memory Cluster), drop the feature.
  1598. //
  1599. if (KeFeatureBits & (KF_PAT | KF_MTRR)) {
  1600. NTSTATUS Status;
  1601. BOOLEAN UseFrameBufferCaching;
  1602. ULONG Size;
  1603. Status = HalQuerySystemInformation(
  1604. HalFrameBufferCachingInformation,
  1605. sizeof(UseFrameBufferCaching),
  1606. &UseFrameBufferCaching,
  1607. &Size
  1608. );
  1609. if (NT_SUCCESS(Status) &&
  1610. (UseFrameBufferCaching == FALSE)) {
  1611. //
  1612. // Hal says don't use.
  1613. //
  1614. KeFeatureBits &= ~(KF_PAT | KF_MTRR);
  1615. }
  1616. }
  1617. //
  1618. // If PAT is supported then initialize it.
  1619. //
  1620. if (KeFeatureBits & KF_PAT) {
  1621. KiInitializePAT();
  1622. }
  1623. //
  1624. // Check to see if the floating point emulator should be used.
  1625. //
  1626. SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
  1627. FALSE;
  1628. switch (KeI386ForceNpxEmulation) {
  1629. case 0:
  1630. //
  1631. // Use the emulator based on the value in KeI386NpxPresent
  1632. //
  1633. break;
  1634. case 1:
  1635. //
  1636. // Only use the emulator if any processor has the known
  1637. // Pentium floating point division problem.
  1638. //
  1639. if (KeI386NpxPresent) {
  1640. //
  1641. // A coprocessor is present, check to see if the precision
  1642. // errata exists.
  1643. //
  1644. double Dividend, Divisor;
  1645. BOOLEAN PrecisionErrata = FALSE;
  1646. ActiveProcessors = KeActiveProcessors;
  1647. for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) {
  1648. if (ActiveProcessors & CurrentAffinity) {
  1649. ActiveProcessors &= ~CurrentAffinity;
  1650. //
  1651. // Run calculation on each processor.
  1652. //
  1653. KeSetSystemAffinityThread(CurrentAffinity);
  1654. _asm {
  1655. ;
  1656. ; This is going to destroy the state in the coprocesssor,
  1657. ; but we know that there's no state currently in it.
  1658. ;
  1659. cli
  1660. mov eax, cr0
  1661. mov ecx, eax ; hold original cr0 value
  1662. and eax, not (CR0_TS+CR0_MP+CR0_EM)
  1663. mov cr0, eax
  1664. fninit ; to known state
  1665. }
  1666. Dividend = 4195835.0;
  1667. Divisor = 3145727.0;
  1668. _asm {
  1669. fld Dividend
  1670. fdiv Divisor ; test known faulty divison
  1671. fmul Divisor ; Multiple quotient by divisor
  1672. fcomp Dividend ; Compare product and dividend
  1673. fstsw ax ; Move float conditions to ax
  1674. sahf ; move to eflags
  1675. mov cr0, ecx ; restore cr0
  1676. sti
  1677. jc short em10
  1678. jz short em20
  1679. em10: mov PrecisionErrata, TRUE
  1680. em20:
  1681. }
  1682. if (PrecisionErrata) {
  1683. KeI386NpxPresent = FALSE;
  1684. SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
  1685. break;
  1686. }
  1687. }
  1688. }
  1689. }
  1690. break;
  1691. default:
  1692. //
  1693. // Unknown setting - use the emulator
  1694. //
  1695. KeI386NpxPresent = FALSE;
  1696. break;
  1697. }
  1698. //
  1699. // Setup processor features, and install emulator if needed
  1700. //
  1701. SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] =
  1702. !KeI386NpxPresent;
  1703. if (!KeI386NpxPresent) {
  1704. //
  1705. // MMx, fast save/restore, streaming SIMD not available when
  1706. // emulator is used. (Nor FP errata).
  1707. //
  1708. KeFeatureBits &= ~(KF_MMX | KF_FXSR | KF_XMMI | KF_XMMI64);
  1709. KeI386XMMIPresent = FALSE;
  1710. KeI386FxsrPresent = FALSE;
  1711. SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
  1712. SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
  1713. SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
  1714. SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
  1715. SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] =
  1716. FALSE;
  1717. }
  1718. //
  1719. // If CR4 exists, enable DE extensions for IO breakpoints
  1720. //
  1721. if (KeFeatureBits & KF_CR4) {
  1722. NumberProcessors = KeNumberProcessors;
  1723. KiIpiGenericCall (
  1724. (PKIPI_BROADCAST_WORKER) Ki386EnableDE,
  1725. (ULONG)(&NumberProcessors)
  1726. );
  1727. }
  1728. //
  1729. // If FXSR feature is supported, set OSFXSR (bit 9) in CR4
  1730. //
  1731. if (KeFeatureBits & KF_FXSR) {
  1732. NumberProcessors = KeNumberProcessors;
  1733. KiIpiGenericCall (
  1734. (PKIPI_BROADCAST_WORKER) Ki386EnableFxsr,
  1735. (ULONG)(&NumberProcessors)
  1736. );
  1737. //
  1738. // If XMMI feature is supported,
  1739. // a. Hook int 19 handler
  1740. // b. Set OSXMMEXCPT (bit 10) in CR4
  1741. // c. Enable use of fast XMMI based zero page routines.
  1742. // d. Remove return instruction at start of prefetch routine.
  1743. //
  1744. if (KeFeatureBits & KF_XMMI) {
  1745. KiIpiGenericCall (
  1746. (PKIPI_BROADCAST_WORKER) Ki386EnableXMMIExceptions,
  1747. (ULONG)(&NumberProcessors)
  1748. );
  1749. KeZeroPage = KiXMMIZeroPage;
  1750. KeZeroPageFromIdleThread = KiXMMIZeroPageNoSave;
  1751. *(PUCHAR)&RtlPrefetchMemoryNonTemporal = 0x90;
  1752. }
  1753. } else {
  1754. #ifndef NT_UP
  1755. //
  1756. // Patch the fxsave instruction in SwapContext to use
  1757. // "fnsave {dd, 31}, fwait {9b}"
  1758. //
  1759. ASSERT( ((ULONG)&ScPatchFxe-(ULONG)&ScPatchFxb) >= 3);
  1760. PatchLocation = (PUCHAR)&ScPatchFxb;
  1761. *PatchLocation++ = 0xdd;
  1762. *PatchLocation++ = 0x31;
  1763. *PatchLocation++ = 0x9b;
  1764. while (PatchLocation < (PUCHAR)&ScPatchFxe) {
  1765. //
  1766. // Put nop's in the remaining bytes
  1767. //
  1768. *PatchLocation++ = 0x90;
  1769. }
  1770. #endif
  1771. }
  1772. //
  1773. // If the system (ie all processors) supports fast system
  1774. // call/return, initialize the machine specific registers
  1775. // required to support it.
  1776. //
  1777. KiRestoreFastSyscallReturnState();
  1778. ActiveProcessors = KeActiveProcessors;
  1779. for (CurrentAffinity=1; ActiveProcessors; CurrentAffinity <<= 1) {
  1780. if (ActiveProcessors & CurrentAffinity) {
  1781. //
  1782. // Switch to that processor, and remove it from the
  1783. // remaining set of processors
  1784. //
  1785. ActiveProcessors &= ~CurrentAffinity;
  1786. KeSetSystemAffinityThread(CurrentAffinity);
  1787. //
  1788. // Determine the MHz for the processor
  1789. //
  1790. KeGetCurrentPrcb()->MHz = 0;
  1791. if (KeFeatureBits & KF_RDTSC) {
  1792. Index = 0;
  1793. pSamp = Samples;
  1794. for (; ;) {
  1795. //
  1796. // Collect a new sample
  1797. // Delay the thread a "long" amount and time it with
  1798. // a time source and RDTSC.
  1799. //
  1800. CPUID (0, &Junk, &Junk, &Junk, &Junk);
  1801. pSamp->PerfStart = KeQueryPerformanceCounter (NULL);
  1802. pSamp->TSCStart = RDTSC();
  1803. pSamp->PerfFreq.QuadPart = -50000;
  1804. KeDelayExecutionThread (KernelMode, FALSE, &pSamp->PerfFreq);
  1805. CPUID (0, &Junk, &Junk, &Junk, &Junk);
  1806. pSamp->PerfEnd = KeQueryPerformanceCounter (&pSamp->PerfFreq);
  1807. pSamp->TSCEnd = RDTSC();
  1808. //
  1809. // Calculate processors MHz
  1810. //
  1811. pSamp->PerfDelta = pSamp->PerfEnd.QuadPart - pSamp->PerfStart.QuadPart;
  1812. pSamp->TSCDelta = pSamp->TSCEnd - pSamp->TSCStart;
  1813. pSamp->MHz = (ULONG) ((pSamp->TSCDelta * pSamp->PerfFreq.QuadPart + 500000L) /
  1814. (pSamp->PerfDelta * 1000000L));
  1815. //
  1816. // If last 2 samples matched within a MHz, done
  1817. //
  1818. if (Index) {
  1819. if (pSamp->MHz == pSamp[-1].MHz ||
  1820. pSamp->MHz == pSamp[-1].MHz + 1 ||
  1821. pSamp->MHz == pSamp[-1].MHz - 1) {
  1822. break;
  1823. }
  1824. }
  1825. //
  1826. // Advance to next sample
  1827. //
  1828. pSamp += 1;
  1829. Index += 1;
  1830. //
  1831. // If too many samples, then something is wrong
  1832. //
  1833. if (Index >= MAX_ATTEMPTS) {
  1834. #if DBG
  1835. //
  1836. // Temp breakpoint to see where this is failing
  1837. // and why
  1838. //
  1839. DbgBreakPoint();
  1840. #endif
  1841. Average = 0;
  1842. for (Index = 0; Index < MAX_ATTEMPTS; Index++) {
  1843. Average += Samples[Index].MHz;
  1844. }
  1845. pSamp[-1].MHz = Average / MAX_ATTEMPTS;
  1846. break;
  1847. }
  1848. }
  1849. KeGetCurrentPrcb()->MHz = (USHORT) pSamp[-1].MHz;
  1850. }
  1851. //
  1852. // If MTRRs are supported and PAT not supported, initialize MTRRs
  1853. // per processor
  1854. //
  1855. if (KeFeatureBits & KF_MTRR) {
  1856. KiInitializeMTRR ( (BOOLEAN) (ActiveProcessors ? FALSE : TRUE));
  1857. }
  1858. //
  1859. // If the processor is a AMD K6 with MTRR support then
  1860. // perform processor specific initialization.
  1861. //
  1862. if (KeFeatureBits & KF_AMDK6MTRR) {
  1863. KiAmdK6InitializeMTRR();
  1864. }
  1865. //
  1866. // Apply Pentium workaround if needed
  1867. //
  1868. if (KiI386PentiumLockErrataPresent) {
  1869. KiI386PentiumLockErrataFixup ();
  1870. }
  1871. //
  1872. // If this processor supports fast floating save/restore,
  1873. // determine the MXCSR mask value that should be used.
  1874. //
  1875. if (KeFeatureBits & KF_FXSR) {
  1876. //
  1877. // Get base of NPX save area.
  1878. //
  1879. //
  1880. PFX_SAVE_AREA NpxFrame;
  1881. KFLOATING_SAVE Save;
  1882. ULONG MXCsrMask = 0xFFBF;
  1883. NpxFrame = (PFX_SAVE_AREA)
  1884. (((ULONG)(KeGetCurrentThread()->InitialStack) -
  1885. sizeof(FX_SAVE_AREA)));
  1886. NpxFrame->U.FxArea.MXCsrMask = 0;
  1887. Kix86FxSave(NpxFrame);
  1888. //
  1889. // If the processor supplied a mask value, use
  1890. // that, otherwise set the default value.
  1891. //
  1892. if (NpxFrame->U.FxArea.MXCsrMask != 0) {
  1893. MXCsrMask = NpxFrame->U.FxArea.MXCsrMask;
  1894. }
  1895. //
  1896. // All processors must use the same (most restrictive)
  1897. // value.
  1898. //
  1899. if (KiMXCsrMask == 0) {
  1900. KiMXCsrMask = MXCsrMask;
  1901. } else if (KiMXCsrMask != MXCsrMask) {
  1902. KeBugCheckEx(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
  1903. KF_FXSR,
  1904. KiMXCsrMask,
  1905. MXCsrMask,
  1906. 0);
  1907. }
  1908. KiMXCsrMask &= MXCsrMask;
  1909. }
  1910. }
  1911. }
  1912. KeRevertToUserAffinityThread();
  1913. return TRUE;
  1914. }
  1915. VOID
  1916. KeOptimizeProcessorControlState (
  1917. VOID
  1918. )
  1919. {
  1920. Ke386ConfigureCyrixProcessor ();
  1921. }
  1922. VOID
  1923. KeSetup80387OrEmulate (
  1924. IN PVOID *R3EmulatorTable
  1925. )
  1926. /*++
  1927. Routine Description:
  1928. This routine is called by PS initialization after loading NTDLL.
  1929. If this is a 386 system without 387s (all processors must be
  1930. symmetrical) then this function will set the trap 07 vector on all
  1931. processors to point to the address passed in (which should be the
  1932. entry point of the 80387 emulator in NTDLL, NPXNPHandler).
  1933. Arguments:
  1934. HandlerAddress - Supplies the address of the trap07 handler.
  1935. Return Value:
  1936. None.
  1937. --*/
  1938. {
  1939. PKINTERRUPT_ROUTINE HandlerAddress;
  1940. KAFFINITY ActiveProcessors, CurrentAffinity;
  1941. KIRQL OldIrql;
  1942. ULONG disposition;
  1943. HANDLE SystemHandle, SourceHandle, DestHandle;
  1944. NTSTATUS Status;
  1945. UNICODE_STRING unicodeString;
  1946. OBJECT_ATTRIBUTES ObjectAttributes;
  1947. if (!KeI386NpxPresent) {
  1948. //
  1949. // Use the user mode floating point emulator
  1950. //
  1951. HandlerAddress = (PKINTERRUPT_ROUTINE) ((PULONG) R3EmulatorTable)[0];
  1952. Ki387RoundModeTable = (PVOID) ((PULONG) R3EmulatorTable)[1];
  1953. ActiveProcessors = KeActiveProcessors;
  1954. for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) {
  1955. if (ActiveProcessors & CurrentAffinity) {
  1956. ActiveProcessors &= ~CurrentAffinity;
  1957. //
  1958. // Run this code on each processor.
  1959. //
  1960. KeSetSystemAffinityThread(CurrentAffinity);
  1961. //
  1962. // Raise IRQL and lock dispatcher database.
  1963. //
  1964. KiLockDispatcherDatabase(&OldIrql);
  1965. //
  1966. // Make the trap 07 IDT entry point at the passed-in handler
  1967. //
  1968. KiSetHandlerAddressToIDT(I386_80387_NP_VECTOR, HandlerAddress);
  1969. KeGetPcr()->IDT[I386_80387_NP_VECTOR].Selector = KGDT_R3_CODE;
  1970. KeGetPcr()->IDT[I386_80387_NP_VECTOR].Access = TRAP332_GATE;
  1971. //
  1972. // Unlock dispatcher database and lower IRQL to its previous value.
  1973. //
  1974. KiUnlockDispatcherDatabase(OldIrql);
  1975. }
  1976. }
  1977. //
  1978. // Set affinity back to the original value.
  1979. //
  1980. KeRevertToUserAffinityThread();
  1981. //
  1982. // Move any entries from ..\System\FloatingPointProcessor to
  1983. // ..\System\DisabledFloatingPointProcessor.
  1984. //
  1985. //
  1986. // Open system tree
  1987. //
  1988. InitializeObjectAttributes(
  1989. &ObjectAttributes,
  1990. &CmRegistryMachineHardwareDescriptionSystemName,
  1991. OBJ_CASE_INSENSITIVE,
  1992. NULL,
  1993. NULL
  1994. );
  1995. Status = ZwOpenKey( &SystemHandle,
  1996. KEY_ALL_ACCESS,
  1997. &ObjectAttributes
  1998. );
  1999. if (NT_SUCCESS(Status)) {
  2000. //
  2001. // Open FloatingPointProcessor key
  2002. //
  2003. InitializeObjectAttributes(
  2004. &ObjectAttributes,
  2005. &CmTypeName[FloatingPointProcessor],
  2006. OBJ_CASE_INSENSITIVE,
  2007. SystemHandle,
  2008. NULL
  2009. );
  2010. Status = ZwOpenKey ( &SourceHandle,
  2011. KEY_ALL_ACCESS,
  2012. &ObjectAttributes
  2013. );
  2014. if (NT_SUCCESS(Status)) {
  2015. //
  2016. // Create DisabledFloatingPointProcessor key
  2017. //
  2018. RtlInitUnicodeString (
  2019. &unicodeString,
  2020. CmDisabledFloatingPointProcessor
  2021. );
  2022. InitializeObjectAttributes(
  2023. &ObjectAttributes,
  2024. &unicodeString,
  2025. OBJ_CASE_INSENSITIVE,
  2026. SystemHandle,
  2027. NULL
  2028. );
  2029. Status = ZwCreateKey( &DestHandle,
  2030. KEY_ALL_ACCESS,
  2031. &ObjectAttributes,
  2032. 0,
  2033. NULL,
  2034. REG_OPTION_VOLATILE,
  2035. &disposition
  2036. );
  2037. if (NT_SUCCESS(Status)) {
  2038. //
  2039. // Move it
  2040. //
  2041. KiMoveRegTree (SourceHandle, DestHandle);
  2042. ZwClose (DestHandle);
  2043. }
  2044. ZwClose (SourceHandle);
  2045. }
  2046. ZwClose (SystemHandle);
  2047. }
  2048. }
  2049. }
  2050. NTSTATUS
  2051. KiMoveRegTree(
  2052. HANDLE Source,
  2053. HANDLE Dest
  2054. )
  2055. {
  2056. NTSTATUS Status;
  2057. PKEY_BASIC_INFORMATION KeyInformation;
  2058. PKEY_VALUE_FULL_INFORMATION KeyValue;
  2059. OBJECT_ATTRIBUTES ObjectAttributes;
  2060. HANDLE SourceChild;
  2061. HANDLE DestChild;
  2062. ULONG ResultLength;
  2063. UCHAR buffer[1024]; // hmm....
  2064. UNICODE_STRING ValueName;
  2065. UNICODE_STRING KeyName;
  2066. KeyValue = (PKEY_VALUE_FULL_INFORMATION)buffer;
  2067. //
  2068. // Move values from source node to dest node
  2069. //
  2070. for (; ;) {
  2071. //
  2072. // Get first value
  2073. //
  2074. Status = ZwEnumerateValueKey(Source,
  2075. 0,
  2076. KeyValueFullInformation,
  2077. buffer,
  2078. sizeof (buffer),
  2079. &ResultLength);
  2080. if (!NT_SUCCESS(Status)) {
  2081. break;
  2082. }
  2083. //
  2084. // Write value to dest node
  2085. //
  2086. ValueName.Buffer = KeyValue->Name;
  2087. ValueName.Length = (USHORT) KeyValue->NameLength;
  2088. ZwSetValueKey( Dest,
  2089. &ValueName,
  2090. KeyValue->TitleIndex,
  2091. KeyValue->Type,
  2092. buffer+KeyValue->DataOffset,
  2093. KeyValue->DataLength
  2094. );
  2095. //
  2096. // Delete value and get first value again
  2097. //
  2098. Status = ZwDeleteValueKey (Source, &ValueName);
  2099. if (!NT_SUCCESS(Status)) {
  2100. break;
  2101. }
  2102. }
  2103. //
  2104. // Enumerate node's children and apply ourselves to each one
  2105. //
  2106. KeyInformation = (PKEY_BASIC_INFORMATION)buffer;
  2107. for (; ;) {
  2108. //
  2109. // Open node's first key
  2110. //
  2111. Status = ZwEnumerateKey(
  2112. Source,
  2113. 0,
  2114. KeyBasicInformation,
  2115. KeyInformation,
  2116. sizeof (buffer),
  2117. &ResultLength
  2118. );
  2119. if (!NT_SUCCESS(Status)) {
  2120. break;
  2121. }
  2122. KeyName.Buffer = KeyInformation->Name;
  2123. KeyName.Length = (USHORT) KeyInformation->NameLength;
  2124. InitializeObjectAttributes(
  2125. &ObjectAttributes,
  2126. &KeyName,
  2127. OBJ_CASE_INSENSITIVE,
  2128. Source,
  2129. NULL
  2130. );
  2131. Status = ZwOpenKey(
  2132. &SourceChild,
  2133. KEY_ALL_ACCESS,
  2134. &ObjectAttributes
  2135. );
  2136. if (!NT_SUCCESS(Status)) {
  2137. break;
  2138. }
  2139. //
  2140. // Create key in dest tree
  2141. //
  2142. InitializeObjectAttributes(
  2143. &ObjectAttributes,
  2144. &KeyName,
  2145. OBJ_CASE_INSENSITIVE,
  2146. Dest,
  2147. NULL
  2148. );
  2149. Status = ZwCreateKey(
  2150. &DestChild,
  2151. KEY_ALL_ACCESS,
  2152. &ObjectAttributes,
  2153. 0,
  2154. NULL,
  2155. REG_OPTION_VOLATILE,
  2156. NULL
  2157. );
  2158. if (!NT_SUCCESS(Status)) {
  2159. break;
  2160. }
  2161. //
  2162. // Move subtree
  2163. //
  2164. Status = KiMoveRegTree(SourceChild, DestChild);
  2165. ZwClose(DestChild);
  2166. ZwClose(SourceChild);
  2167. if (!NT_SUCCESS(Status)) {
  2168. break;
  2169. }
  2170. //
  2171. // Loop and get first key. (old first key was deleted by the
  2172. // call to KiMoveRegTree).
  2173. //
  2174. }
  2175. //
  2176. // Remove source node
  2177. //
  2178. return NtDeleteKey (Source);
  2179. }
  2180. VOID
  2181. KiI386PentiumLockErrataFixup (
  2182. VOID
  2183. )
  2184. /*++
  2185. Routine Description:
  2186. This routine is called once on every processor when
  2187. KiI386PentiumLockErrataPresent is TRUE.
  2188. This routine replaces the local IDT with an IDT that has the first 7 IDT
  2189. entries on their own page and returns the first page to the caller to
  2190. be marked as read-only. This causes the processor to trap-0e fault when
  2191. the errata occurs. Special code in the trap-0e handler detects the
  2192. problem and performs the proper fixup.
  2193. Arguments:
  2194. FixupPage - Returns a virtual address of a page to be marked read-only
  2195. Return Value:
  2196. None.
  2197. --*/
  2198. {
  2199. KDESCRIPTOR IdtDescriptor;
  2200. ULONG OrginalBase;
  2201. PUCHAR NewBase, BasePage;
  2202. BOOLEAN Enable;
  2203. BOOLEAN Status;
  2204. #define IDT_SKIP (7 * sizeof (KIDTENTRY))
  2205. //
  2206. // Allocate memory for a new copy of the processor's IDT
  2207. //
  2208. BasePage = MmAllocateIndependentPages (2*PAGE_SIZE, 0);
  2209. //
  2210. // The IDT base is such that the first 7 entries are on the
  2211. // first (read-only) page, and the remaining entries are on the
  2212. // second (read-write) page
  2213. //
  2214. NewBase = BasePage + PAGE_SIZE - IDT_SKIP;
  2215. //
  2216. // Disable interrupts on this processor while updating the IDT base
  2217. //
  2218. Enable = KeDisableInterrupts();
  2219. //
  2220. // Copy Old IDT to new IDT
  2221. //
  2222. _asm {
  2223. sidt IdtDescriptor.Limit
  2224. }
  2225. RtlCopyMemory ((PVOID) NewBase,
  2226. (PVOID) IdtDescriptor.Base,
  2227. IdtDescriptor.Limit + 1
  2228. );
  2229. IdtDescriptor.Base = (ULONG) NewBase;
  2230. //
  2231. // Set the new IDT
  2232. //
  2233. _asm {
  2234. lidt IdtDescriptor.Limit
  2235. }
  2236. //
  2237. // Update the PCR
  2238. //
  2239. KeGetPcr()->IDT = (PKIDTENTRY) NewBase;
  2240. //
  2241. // Restore interrupts
  2242. //
  2243. KeEnableInterrupts(Enable);
  2244. //
  2245. // Mark the first page which contains IDT entries 0-6 as read-only
  2246. //
  2247. Status = MmSetPageProtection (BasePage, PAGE_SIZE, PAGE_READONLY);
  2248. ASSERT (Status);
  2249. }
  2250. VOID
  2251. KiLogMcaErrors (
  2252. VOID
  2253. )
  2254. /*++
  2255. Routine Description:
  2256. This routine is called to check for remembered machine checks.
  2257. If a machine check crashed the system, this is the last chance
  2258. to save information about it, at the time the system reboots.
  2259. Arguments:
  2260. none
  2261. Return Value:
  2262. none
  2263. --*/
  2264. {
  2265. PIO_ERROR_LOG_PACKET ErrLog;
  2266. MCA_EXCEPTION Exception;
  2267. PKPRCB Prcb;
  2268. PWSTR PDest;
  2269. PWSTR PSrc;
  2270. WCHAR PString[20];
  2271. NTSTATUS Status;
  2272. ULONG ToDo;
  2273. ULONG Length;
  2274. PUCHAR PData;
  2275. ULONG RegSet;
  2276. KAFFINITY ActiveProcessors, CurrentAffinity;
  2277. HAL_MCA_INTERFACE Mca;
  2278. UCHAR BankNumber;
  2279. //
  2280. // Current Pentium IIIs don't support the retention of machine
  2281. // check information across a warm reset. This should've meant
  2282. // that this function wouldn't generate any eventlog entries on
  2283. // those processors. However, this code was logging non-fatal
  2284. // MCAs created by BIOS initialization resulting in spurious
  2285. // eventlog entries that did not indicate a reliability problem.
  2286. //
  2287. // Now this code is only run on Intel processors that are
  2288. // Pentium 4-derived or later i.e. where the MCA warm reset retention
  2289. // functionality is definitely implemented.
  2290. //
  2291. Prcb = KeGetCurrentPrcb();
  2292. if ((strcmp((PCHAR) Prcb->VendorString, CmpIntelID) == 0) &&
  2293. (KeProcessorLevel < 0xF)) {
  2294. return;
  2295. }
  2296. //
  2297. // Obtain the HAL interface to the Machine Check Architecture
  2298. // register set.
  2299. //
  2300. Status = HalQuerySystemInformation(HalQueryMcaInterface,
  2301. sizeof(Mca),
  2302. &Mca,
  2303. &Length);
  2304. if (Status != STATUS_SUCCESS) {
  2305. return;
  2306. }
  2307. ASSERT(Length == sizeof(Mca));
  2308. //
  2309. // Clear the exception data and indicate to the HAL that we
  2310. // support extended MCA data. (VersionNumber = 2).
  2311. //
  2312. RtlZeroMemory(&Exception, sizeof(Exception));
  2313. Exception.VersionNumber = 2;
  2314. //
  2315. // Obtain exclusive access to the MCA registers.
  2316. //
  2317. Mca.Lock();
  2318. //
  2319. // Check for remembered machine check errors on each processor
  2320. // in the system.
  2321. //
  2322. ActiveProcessors = KeActiveProcessors;
  2323. for (CurrentAffinity = 1; ActiveProcessors; CurrentAffinity <<= 1) {
  2324. if ((CurrentAffinity & ActiveProcessors) == 0) {
  2325. continue;
  2326. }
  2327. ActiveProcessors ^= CurrentAffinity;
  2328. KeSetSystemAffinityThread(CurrentAffinity);
  2329. //
  2330. // Look for a machine check on this processor.
  2331. //
  2332. for (BankNumber = 0; TRUE; BankNumber++) {
  2333. Status = Mca.ReadRegister(BankNumber, &Exception);
  2334. if (Status == STATUS_UNSUCCESSFUL) {
  2335. //
  2336. // No error this bank, examine next.
  2337. //
  2338. continue;
  2339. }
  2340. if (Status != STATUS_SUCCESS) {
  2341. //
  2342. // No such register, done looking on this processor.
  2343. //
  2344. break;
  2345. }
  2346. //
  2347. // Have a machine check, try to report it.
  2348. //
  2349. ErrLog = IoAllocateGenericErrorLogEntry(ERROR_LOG_MAXIMUM_SIZE);
  2350. if (!ErrLog) {
  2351. //
  2352. // Unable to allocate an error log entry? Give up.
  2353. //
  2354. break;
  2355. }
  2356. //
  2357. // Fill it in and write it out.
  2358. //
  2359. // "Application popup: %1 %2"
  2360. //
  2361. ErrLog->DumpDataSize = (USHORT)MCA_EXCEPTION_V1_SIZE;
  2362. ErrLog->NumberOfStrings = 0;
  2363. ErrLog->StringOffset =
  2364. FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  2365. + MCA_EXCEPTION_V1_SIZE;
  2366. ErrLog->StringOffset =
  2367. (ErrLog->StringOffset + sizeof(PWSTR)-1)
  2368. / sizeof(PWSTR);
  2369. ErrLog->StringOffset *= sizeof(PWSTR);
  2370. ErrLog->ErrorCode = STATUS_LOG_HARD_ERROR;
  2371. ErrLog->UniqueErrorValue = Exception.u.Mca.BankNumber;
  2372. ErrLog->FinalStatus = STATUS_LOG_HARD_ERROR;
  2373. RtlCopyMemory(ErrLog->DumpData, &Exception, MCA_EXCEPTION_V1_SIZE);
  2374. PDest = (PWSTR)((PCHAR)ErrLog+ErrLog->StringOffset);
  2375. PSrc = L"Machine Check:";
  2376. RtlCopyMemory(PDest, PSrc, (wcslen(PSrc)+1) * sizeof(WCHAR));
  2377. PDest += wcslen(PSrc)+1;
  2378. ErrLog->NumberOfStrings++;
  2379. PSrc = L"Banks";
  2380. RtlCopyMemory(PDest, PSrc, (wcslen(PSrc)+1) * sizeof(WCHAR));
  2381. PDest += wcslen(PSrc)+1;
  2382. ErrLog->NumberOfStrings++;
  2383. IoWriteErrorLogEntry(ErrLog);
  2384. //
  2385. // There are Exception.ExtCnt entries in Exception.ExtReg,
  2386. // plus Exception.ExtCnt itself.
  2387. //
  2388. ToDo = (Exception.ExtCnt+1) * sizeof(Exception.ExtReg[0]);
  2389. PData = ((PUCHAR)&Exception)+MCA_EXCEPTION_V1_SIZE;
  2390. RegSet = 0;
  2391. while (ToDo > 0) {
  2392. //
  2393. // Have additional machine check data, try to report it.
  2394. //
  2395. if (ToDo > 8 * sizeof(ULONGLONG)) {
  2396. Length = 8 * sizeof(ULONGLONG);
  2397. } else {
  2398. Length = ToDo;
  2399. }
  2400. ErrLog = IoAllocateGenericErrorLogEntry(ERROR_LOG_MAXIMUM_SIZE);
  2401. if (!ErrLog) {
  2402. break; // Inner loop only
  2403. }
  2404. //
  2405. // Fill it in and write it out.
  2406. //
  2407. // "Application popup: %1 %2"
  2408. //
  2409. ErrLog->DumpDataSize = (USHORT)Length;
  2410. ErrLog->NumberOfStrings = 0;
  2411. ErrLog->StringOffset =
  2412. FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)
  2413. + (USHORT)Length;
  2414. ErrLog->StringOffset =
  2415. (ErrLog->StringOffset + sizeof(PWSTR)-1)
  2416. / sizeof(PWSTR);
  2417. ErrLog->StringOffset *= sizeof(PWSTR);
  2418. ErrLog->ErrorCode = STATUS_LOG_HARD_ERROR;
  2419. ErrLog->UniqueErrorValue = RegSet;
  2420. ErrLog->FinalStatus = STATUS_LOG_HARD_ERROR;
  2421. RtlCopyMemory(ErrLog->DumpData, PData, Length);
  2422. PDest = (PWSTR)((PCHAR)ErrLog+ErrLog->StringOffset);
  2423. PSrc = L"Machine Check: Regs";
  2424. RtlCopyMemory(PDest, PSrc, (wcslen(PSrc)+1) * sizeof(WCHAR));
  2425. PDest += wcslen(PSrc)+1;
  2426. ErrLog->NumberOfStrings++;
  2427. PSrc = _itow(RegSet, PString, 10);
  2428. RtlCopyMemory(PDest, PSrc, (wcslen(PSrc)+1) * sizeof(WCHAR));
  2429. PDest += wcslen(PSrc)+1;
  2430. ErrLog->NumberOfStrings++;
  2431. IoWriteErrorLogEntry(ErrLog);
  2432. PData += Length;
  2433. ToDo -= Length;
  2434. RegSet+= 8;
  2435. }
  2436. //
  2437. // Reset for next iteration.
  2438. //
  2439. RtlZeroMemory(&Exception, sizeof(Exception));
  2440. Exception.VersionNumber = 2;
  2441. }
  2442. }
  2443. KeRevertToUserAffinityThread();
  2444. Mca.Unlock();
  2445. }