Leaked source code of windows server 2003
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.

1112 lines
25 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. initkr.c
  5. Abstract:
  6. This module contains the code to initialize the kernel data structures
  7. and to initialize the idle thread, its process, the processor control
  8. block, and the processor control region.
  9. Author:
  10. David N. Cutler (davec) 22-Apr-2000
  11. Environment:
  12. Kernel mode only.
  13. --*/
  14. #include "ki.h"
  15. //
  16. // Define default profile IRQL level.
  17. //
  18. KIRQL KiProfileIrql = PROFILE_LEVEL;
  19. //
  20. // Define the process and thread for the initial system process and startup
  21. // thread.
  22. //
  23. EPROCESS KiInitialProcess;
  24. ETHREAD KiInitialThread;
  25. //
  26. // Define the interrupt initialization data.
  27. //
  28. // Entries in the KiInterruptInitTable[] must be in ascending vector # order.
  29. //
  30. typedef VOID (*KI_INTERRUPT_HANDLER)(VOID);
  31. typedef struct _KI_INTINIT_REC {
  32. UCHAR Vector;
  33. UCHAR Dpl;
  34. UCHAR IstIndex;
  35. KI_INTERRUPT_HANDLER Handler;
  36. } KI_INTINIT_REC, *PKI_INTINIT_REC;
  37. #pragma data_seg("INITDATA")
  38. KI_INTINIT_REC KiInterruptInitTable[] = {
  39. {0, 0, 0, KiDivideErrorFault},
  40. {1, 0, 0, KiDebugTrapOrFault},
  41. {2, 0, TSS_IST_PANIC, KiNmiInterrupt},
  42. {3, 3, 0, KiBreakpointTrap},
  43. {4, 3, 0, KiOverflowTrap},
  44. {5, 0, 0, KiBoundFault},
  45. {6, 0, 0, KiInvalidOpcodeFault},
  46. {7, 0, 0, KiNpxNotAvailableFault},
  47. {8, 0, TSS_IST_PANIC, KiDoubleFaultAbort},
  48. {9, 0, 0, KiNpxSegmentOverrunAbort},
  49. {10, 0, 0, KiInvalidTssFault},
  50. {11, 0, 0, KiSegmentNotPresentFault},
  51. {12, 0, 0, KiStackFault},
  52. {13, 0, 0, KiGeneralProtectionFault},
  53. {14, 0, 0, KiPageFault},
  54. {16, 0, 0, KiFloatingErrorFault},
  55. {17, 0, 0, KiAlignmentFault},
  56. {18, 0, TSS_IST_MCA, KiMcheckAbort},
  57. {19, 0, 0, KiXmmException},
  58. {31, 0, 0, KiApcInterrupt},
  59. {45, 3, 0, KiDebugServiceTrap},
  60. {47, 0, 0, KiDpcInterrupt},
  61. {0, 0, 0, NULL}
  62. };
  63. #pragma data_seg()
  64. //
  65. // Define macro to initialize an IDT entry.
  66. //
  67. // KiInitializeIdtEntry (
  68. // IN PKIDTENTRY64 Entry,
  69. // IN PVOID Address,
  70. // IN USHORT Level
  71. // )
  72. //
  73. // Arguments:
  74. //
  75. // Entry - Supplies a pointer to an IDT entry.
  76. //
  77. // Address - Supplies the address of the vector routine.
  78. //
  79. // Dpl - Descriptor privilege level.
  80. //
  81. // Ist - Interrupt stack index.
  82. //
  83. #define KiInitializeIdtEntry(Entry, Address, Level, Index) \
  84. (Entry)->OffsetLow = (USHORT)((ULONG64)(Address)); \
  85. (Entry)->Selector = KGDT64_R0_CODE; \
  86. (Entry)->IstIndex = Index; \
  87. (Entry)->Type = 0xe; \
  88. (Entry)->Dpl = (Level); \
  89. (Entry)->Present = 1; \
  90. (Entry)->OffsetMiddle = (USHORT)((ULONG64)(Address) >> 16); \
  91. (Entry)->OffsetHigh = (ULONG)((ULONG64)(Address) >> 32) \
  92. //
  93. // Define forward referenced prototypes.
  94. //
  95. ULONG
  96. KiFatalFilter (
  97. IN ULONG Code,
  98. IN PEXCEPTION_POINTERS Pointers
  99. );
  100. VOID
  101. KiSetCacheInformation (
  102. VOID
  103. );
  104. VOID
  105. KiSetCpuVendor (
  106. VOID
  107. );
  108. VOID
  109. KiSetFeatureBits (
  110. IN PKPRCB Prcb
  111. );
  112. VOID
  113. KiSetProcessorType (
  114. VOID
  115. );
  116. #pragma alloc_text(INIT, KiFatalFilter)
  117. #pragma alloc_text(INIT, KiInitializeBootStructures)
  118. #pragma alloc_text(INIT, KiInitializeKernel)
  119. #pragma alloc_text(INIT, KiInitMachineDependent)
  120. #pragma alloc_text(INIT, KiSetCacheInformation)
  121. #pragma alloc_text(INIT, KiSetCpuVendor)
  122. #pragma alloc_text(INIT, KiSetFeatureBits)
  123. #pragma alloc_text(INIT, KiSetProcessorType)
  124. VOID
  125. KiInitializeKernel (
  126. IN PKPROCESS Process,
  127. IN PKTHREAD Thread,
  128. IN PVOID IdleStack,
  129. IN PKPRCB Prcb,
  130. IN CCHAR Number,
  131. PLOADER_PARAMETER_BLOCK LoaderBlock
  132. )
  133. /*++
  134. Routine Description:
  135. This function gains control after the system has been booted, but before
  136. the system has been completely initialized. Its function is to initialize
  137. the kernel data structures, initialize the idle thread and process objects,
  138. complete the initialization of the processor control block (PRCB) and
  139. processor control region (PCR), call the executive initialization routine,
  140. then return to the system startup routine. This routine is also called to
  141. initialize the processor specific structures when a new processor is
  142. brought on line.
  143. Arguments:
  144. Process - Supplies a pointer to a control object of type process for
  145. the specified processor.
  146. Thread - Supplies a pointer to a dispatcher object of type thread for
  147. the specified processor.
  148. IdleStack - Supplies a pointer the base of the real kernel stack for
  149. idle thread on the specified processor.
  150. Prcb - Supplies a pointer to a processor control block for the specified
  151. processor.
  152. Number - Supplies the number of the processor that is being
  153. initialized.
  154. LoaderBlock - Supplies a pointer to the loader parameter block.
  155. Return Value:
  156. None.
  157. --*/
  158. {
  159. ULONG64 DirectoryTableBase[2];
  160. ULONG FeatureBits;
  161. #if !defined(NT_UP)
  162. LONG Index;
  163. #endif
  164. KIRQL OldIrql;
  165. PCHAR Options;
  166. //
  167. // Set CPU vendor.
  168. //
  169. KiSetCpuVendor();
  170. //
  171. // Set processor type.
  172. //
  173. KiSetProcessorType();
  174. //
  175. // Set the processor feature bits.
  176. //
  177. KiSetFeatureBits(Prcb);
  178. FeatureBits = Prcb->FeatureBits;
  179. //
  180. // If this is the boot processor, then enable global pages, set the page
  181. // attributes table, set machine check enable, set large page enable, and
  182. // enable debug extensions.
  183. //
  184. // N.B. This only happens on the boot processor and at a time when there
  185. // can be no coherency problem. On subsequent, processors this happens
  186. // during the transistion into 64-bit mode which is also at a time
  187. // that there can be no coherency problems.
  188. //
  189. if (Number == 0) {
  190. //
  191. // If any loader options were specified, then upper case the options.
  192. //
  193. Options = LoaderBlock->LoadOptions;
  194. if (Options != NULL) {
  195. _strupr(Options);
  196. }
  197. //
  198. // Flush the entire TB and enable global pages.
  199. //
  200. KeFlushCurrentTb();
  201. //
  202. // Set page attributes table and flush cache.
  203. //
  204. KiSetPageAttributesTable();
  205. WritebackInvalidate();
  206. //
  207. // If execute protection is specified in the loader options, then
  208. // turn off no execute protection for memory management.
  209. //
  210. // N.B. No execute protection is always enabled during processor
  211. // initialization.
  212. //
  213. MmPaeMask = 0x8000000000000000UI64;
  214. MmPaeErrMask = 0x8;
  215. if ((strstr(Options, "NOEXECUTE") == NULL) &&
  216. (strstr(Options, "EXECUTE") != NULL)) {
  217. MmPaeMask = 0;
  218. MmPaeErrMask = 0;
  219. }
  220. //
  221. // Set debugger extension and large page enable.
  222. //
  223. WriteCR4(ReadCR4() | CR4_DE | CR4_PSE);
  224. //
  225. // Flush the entire TB.
  226. //
  227. KeFlushCurrentTb();
  228. }
  229. //
  230. // set processor cache size information.
  231. //
  232. KiSetCacheInformation();
  233. //
  234. // Initialize power state information.
  235. //
  236. PoInitializePrcb(Prcb);
  237. //
  238. // initialize the per processor lock data.
  239. //
  240. KiInitSpinLocks(Prcb, Number);
  241. //
  242. // If the initial processor is being initialized, then initialize the
  243. // per system data structures.
  244. //
  245. if (Number == 0) {
  246. //
  247. // Set default node until the node topology is available.
  248. //
  249. KeNodeBlock[0] = &KiNode0;
  250. #if !defined(NT_UP)
  251. for (Index = 1; Index < MAXIMUM_CCNUMA_NODES; Index += 1) {
  252. KeNodeBlock[Index] = &KiNodeInit[Index];
  253. }
  254. #endif
  255. Prcb->ParentNode = KeNodeBlock[0];
  256. KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
  257. //
  258. // Set global architecture and feature information.
  259. //
  260. KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64;
  261. KeProcessorLevel = (USHORT)Prcb->CpuType;
  262. KeProcessorRevision = Prcb->CpuStep;
  263. KeFeatureBits = FeatureBits;
  264. //
  265. // Lower IRQL to APC level.
  266. //
  267. KeLowerIrql(APC_LEVEL);
  268. //
  269. // Initialize kernel internal spinlocks
  270. //
  271. KeInitializeSpinLock(&KiFreezeExecutionLock);
  272. //
  273. // Performance architecture independent initialization.
  274. //
  275. KiInitSystem();
  276. //
  277. // Initialize idle thread process object and then set:
  278. //
  279. // 1. the process quantum.
  280. //
  281. DirectoryTableBase[0] = 0;
  282. DirectoryTableBase[1] = 0;
  283. KeInitializeProcess(Process,
  284. (KPRIORITY)0,
  285. (KAFFINITY)(-1),
  286. &DirectoryTableBase[0],
  287. FALSE);
  288. Process->ThreadQuantum = MAXCHAR;
  289. } else {
  290. //
  291. // If the CPU feature bits are not identical, then bugcheck.
  292. //
  293. if (FeatureBits != KeFeatureBits) {
  294. KeBugCheckEx(MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED,
  295. (ULONG64)FeatureBits,
  296. (ULONG64)KeFeatureBits,
  297. 0,
  298. 0);
  299. }
  300. //
  301. // Lower IRQL to DISPATCH level.
  302. //
  303. KeLowerIrql(DISPATCH_LEVEL);
  304. }
  305. //
  306. // Set global processor features.
  307. //
  308. SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
  309. SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
  310. SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] = TRUE;
  311. SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = TRUE;
  312. SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = TRUE;
  313. SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = TRUE;
  314. if (FeatureBits & KF_3DNOW) {
  315. SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = TRUE;
  316. }
  317. //
  318. // Initialize idle thread object and then set:
  319. //
  320. // 1. the next processor number to the specified processor.
  321. // 2. the thread priority to the highest possible value.
  322. // 3. the state of the thread to running.
  323. // 4. the thread affinity to the specified processor.
  324. // 5. the specified member in the process active processors set.
  325. //
  326. KeInitializeThread(Thread,
  327. (PVOID)((ULONG64)IdleStack),
  328. NULL,
  329. NULL,
  330. NULL,
  331. NULL,
  332. NULL,
  333. Process);
  334. Thread->NextProcessor = Number;
  335. Thread->Priority = HIGH_PRIORITY;
  336. Thread->State = Running;
  337. Thread->Affinity = AFFINITY_MASK(Number);
  338. Thread->WaitIrql = DISPATCH_LEVEL;
  339. Process->ActiveProcessors |= AFFINITY_MASK(Number);
  340. //
  341. // Call the executive initialization routine.
  342. //
  343. try {
  344. ExpInitializeExecutive(Number, LoaderBlock);
  345. } except(KiFatalFilter(GetExceptionCode(), GetExceptionInformation())) {
  346. }
  347. //
  348. // If the initial processor is being initialized, then compute the timer
  349. // table reciprocal value, reset the PRCB values for the controllable DPC
  350. // behavior in order to reflect any registry overrides, and initialize the
  351. // global unwind history table.
  352. //
  353. if (Number == 0) {
  354. KiTimeIncrementReciprocal = KiComputeReciprocal((LONG)KeMaximumIncrement,
  355. &KiTimeIncrementShiftCount);
  356. Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
  357. Prcb->MinimumDpcRate = KiMinimumDpcRate;
  358. Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
  359. RtlInitializeHistoryTable();
  360. }
  361. //
  362. // Raise IRQL to dispatch level and eet the priority of the idle thread
  363. // to zero. This will have the effect of immediately causing the phase
  364. // one initialization thread to get scheduled for execution. The idle
  365. // thread priority is then set ot the lowest realtime priority.
  366. //
  367. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  368. KeSetPriorityThread(Thread, 0);
  369. Thread->Priority = LOW_REALTIME_PRIORITY;
  370. //
  371. // Raise IRQL to highest level.
  372. //
  373. KeRaiseIrql(HIGH_LEVEL, &OldIrql);
  374. //
  375. // If the current processor is a secondary processor and a thread has
  376. // not been selected for execution, then set the appropriate bit in the
  377. // idle summary.
  378. //
  379. #if !defined(NT_UP)
  380. KiAcquirePrcbLock(Prcb);
  381. if ((Number != 0) && (Prcb->NextThread == NULL)) {
  382. KiIdleSummary |= AFFINITY_MASK(Number);
  383. }
  384. KiReleasePrcbLock(Prcb);
  385. #endif
  386. //
  387. // Signal that this processor has completed its initialization.
  388. //
  389. LoaderBlock->Prcb = (ULONG64)NULL;
  390. return;
  391. }
  392. VOID
  393. KiInitializeBootStructures (
  394. PLOADER_PARAMETER_BLOCK LoaderBlock
  395. )
  396. /*++
  397. Routine Description:
  398. This function initializes the boot structures for a processor. It is only
  399. called by the system start up code. Certain fields in the boot structures
  400. have already been initialized. In particular:
  401. The address and limit of the GDT and IDT in the PCR.
  402. The address of the system TSS in the PCR.
  403. The processor number in the PCR.
  404. The special registers in the PRCB.
  405. N.B. All uninitialized fields are zero.
  406. Arguments:
  407. LoaderBlock - Supplies a pointer to the loader block that has been
  408. initialized for this processor.
  409. Return Value:
  410. None.
  411. --*/
  412. {
  413. PKIDTENTRY64 IdtBase;
  414. ULONG Index;
  415. PKI_INTINIT_REC IntInitRec;
  416. PKPCR Pcr = KeGetPcr();
  417. PKPRCB Prcb = KeGetCurrentPrcb();
  418. UCHAR Number;
  419. PKTHREAD Thread;
  420. PKTSS64 TssBase;
  421. //
  422. // Initialize the PCR major and minor version numbers.
  423. //
  424. Pcr->MajorVersion = PCR_MAJOR_VERSION;
  425. Pcr->MinorVersion = PCR_MINOR_VERSION;
  426. //
  427. // initialize the PRCB major and minor version numbers and build type.
  428. //
  429. Prcb->MajorVersion = PRCB_MAJOR_VERSION;
  430. Prcb->MinorVersion = PRCB_MINOR_VERSION;
  431. Prcb->BuildType = 0;
  432. #if DBG
  433. Prcb->BuildType |= PRCB_BUILD_DEBUG;
  434. #endif
  435. #if defined(NT_UP)
  436. Prcb->BuildType |= PRCB_BUILD_UNIPROCESSOR;
  437. #endif
  438. //
  439. // Initialize the PRCR processor number and the PCR and PRCB set member.
  440. //
  441. Number = Pcr->Number;
  442. Prcb->Number = Number;
  443. Prcb->SetMember = AFFINITY_MASK(Number);
  444. Prcb->NotSetMember = ~Prcb->SetMember;
  445. Pcr->SetMember = Prcb->SetMember;
  446. //
  447. // If this is processor zero, then initialize the address of the system
  448. // process and initial thread.
  449. //
  450. if (Number == 0) {
  451. LoaderBlock->Process = (ULONG64)&KiInitialProcess;
  452. LoaderBlock->Thread = (ULONG64)&KiInitialThread;
  453. }
  454. //
  455. // Initialize the PRCB scheduling thread address and the thread process
  456. // address.
  457. //
  458. Thread = (PVOID)LoaderBlock->Thread;
  459. Prcb->CurrentThread = Thread;
  460. Prcb->NextThread = NULL;
  461. Prcb->IdleThread = Thread;
  462. Thread->ApcState.Process = (PKPROCESS)LoaderBlock->Process;
  463. InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
  464. //
  465. // Initialize the processor block address.
  466. //
  467. KiProcessorBlock[Number] = Prcb;
  468. //
  469. // Initialize the PRCB address of the DPC stack.
  470. //
  471. Prcb->DpcStack = (PVOID)LoaderBlock->KernelStack;
  472. //
  473. // Initialize the PRCB symmetric multithreading member.
  474. //
  475. Prcb->MultiThreadProcessorSet = Prcb->SetMember;
  476. //
  477. // If this is processor zero, initialize the IDT according to the contents
  478. // of KiInterruptInitTable[]
  479. //
  480. if (Number == 0) {
  481. IdtBase = Pcr->IdtBase;
  482. IntInitRec = KiInterruptInitTable;
  483. for (Index = 0; Index < MAXIMUM_IDTVECTOR; Index += 1) {
  484. //
  485. // If the vector is found in the initialization table then
  486. // set up the IDT entry accordingly and advance to the next
  487. // entry in the initialization table.
  488. //
  489. // Otherwise set the IDT to reference the unexpected interrupt
  490. // handler.
  491. //
  492. if (Index == IntInitRec->Vector) {
  493. KiInitializeIdtEntry(&IdtBase[Index],
  494. IntInitRec->Handler,
  495. IntInitRec->Dpl,
  496. IntInitRec->IstIndex);
  497. IntInitRec += 1;
  498. } else {
  499. KiInitializeIdtEntry(&IdtBase[Index],
  500. &KxUnexpectedInterrupt0[Index],
  501. 0,
  502. 0);
  503. }
  504. }
  505. }
  506. //
  507. // Initialize the system TSS I/O Map.
  508. //
  509. TssBase = Pcr->TssBase;
  510. TssBase->IoMapBase = KiComputeIopmOffset(FALSE);
  511. //
  512. // Initialize the system call MSRs.
  513. //
  514. // N.B. CSTAR must be written before LSTAR to work around a bug in the
  515. // simulator.
  516. //
  517. WriteMSR(MSR_STAR,
  518. ((ULONG64)KGDT64_R0_CODE << 32) | (((ULONG64)KGDT64_R3_CMCODE | RPL_MASK) << 48));
  519. WriteMSR(MSR_CSTAR, (ULONG64)&KiSystemCall32);
  520. WriteMSR(MSR_LSTAR, (ULONG64)&KiSystemCall64);
  521. WriteMSR(MSR_SYSCALL_MASK, EFLAGS_IF_MASK | EFLAGS_TF_MASK);
  522. //
  523. // Initialize the HAL for this processor.
  524. //
  525. HalInitializeProcessor(Number, LoaderBlock);
  526. //
  527. // Set the appropriate member in the active processors set.
  528. //
  529. KeActiveProcessors |= AFFINITY_MASK(Number);
  530. //
  531. // Set the number of processors based on the maximum of the current
  532. // number of processors and the current processor number.
  533. //
  534. if ((Number + 1) > KeNumberProcessors) {
  535. KeNumberProcessors = Number + 1;
  536. }
  537. return;
  538. }
  539. ULONG
  540. KiFatalFilter (
  541. IN ULONG Code,
  542. IN PEXCEPTION_POINTERS Pointers
  543. )
  544. /*++
  545. Routine Description:
  546. This function is executed if an unhandled exception occurs during
  547. phase 0 initialization. Its function is to bug check the system
  548. with all the context information still on the stack.
  549. Arguments:
  550. Code - Supplies the exception code.
  551. Pointers - Supplies a pointer to the exception information.
  552. Return Value:
  553. None - There is no return from this routine even though it appears there
  554. is.
  555. --*/
  556. {
  557. KeBugCheckEx(PHASE0_EXCEPTION,
  558. Code,
  559. (ULONG64)Pointers,
  560. 0,
  561. 0);
  562. }
  563. BOOLEAN
  564. KiInitMachineDependent (
  565. VOID
  566. )
  567. /*++
  568. Routine Description:
  569. This function initializes machine dependent data structures and hardware.
  570. Arguments:
  571. None.
  572. Return Value:
  573. None.
  574. --*/
  575. {
  576. ULONG Size;
  577. NTSTATUS Status;
  578. BOOLEAN UseFrameBufferCaching;
  579. //
  580. // Query the HAL to determine if the write combining can be used for the
  581. // frame buffer.
  582. //
  583. Status = HalQuerySystemInformation(HalFrameBufferCachingInformation,
  584. sizeof(BOOLEAN),
  585. &UseFrameBufferCaching,
  586. &Size);
  587. //
  588. // If the status is successful and frame buffer caching is disabled,
  589. // then don't enable write combining.
  590. //
  591. if (!NT_SUCCESS(Status) || (UseFrameBufferCaching != FALSE)) {
  592. MmEnablePAT();
  593. }
  594. return TRUE;
  595. }
  596. VOID
  597. KiSetCacheInformation (
  598. VOID
  599. )
  600. /*++
  601. Routine Description:
  602. This function sets the current processor cache information in the PCR.
  603. Arguments:
  604. None.
  605. Return Value:
  606. None.
  607. --*/
  608. {
  609. UCHAR Associativity;
  610. ULONG CacheSize;
  611. CPU_INFO CpuInfo;
  612. ULONG LineSize;
  613. PKPCR Pcr = KeGetPcr();
  614. //
  615. // Get the CPU L2 cache information.
  616. //
  617. KiCpuId(0x80000006, &CpuInfo);
  618. //
  619. // Get the L2 cache line size.
  620. //
  621. LineSize = CpuInfo.Ecx & 0xff;
  622. //
  623. // Get the L2 cache size.
  624. //
  625. CacheSize = (CpuInfo.Ecx >> 16) << 10;
  626. //
  627. // Compute the L2 cache associativity.
  628. //
  629. switch ((CpuInfo.Ecx >> 12) & 0xf) {
  630. //
  631. // Two way set associative.
  632. //
  633. case 2:
  634. Associativity = 2;
  635. break;
  636. //
  637. // Four way set associative.
  638. //
  639. case 4:
  640. Associativity = 4;
  641. break;
  642. //
  643. // Six way set associative.
  644. //
  645. case 6:
  646. Associativity = 6;
  647. break;
  648. //
  649. // Eight way set associative.
  650. //
  651. case 8:
  652. Associativity = 8;
  653. break;
  654. //
  655. // Fully associative.
  656. //
  657. case 255:
  658. Associativity = 16;
  659. break;
  660. //
  661. // Direct mapped.
  662. //
  663. default:
  664. Associativity = 1;
  665. break;
  666. }
  667. //
  668. // Set L2 cache information.
  669. //
  670. Pcr->SecondLevelCacheAssociativity = Associativity;
  671. Pcr->SecondLevelCacheSize = CacheSize;
  672. //
  673. // If the line size is greater then the current largest line size, then
  674. // set the new largest line size.
  675. //
  676. if (LineSize > KeLargestCacheLine) {
  677. KeLargestCacheLine = LineSize;
  678. }
  679. return;
  680. }
  681. VOID
  682. KiSetCpuVendor (
  683. VOID
  684. )
  685. /*++
  686. Routine Description:
  687. Set the current processor cpu vendor information in the PRCB.
  688. Arguments:
  689. None.
  690. Return Value:
  691. None.
  692. --*/
  693. {
  694. PKPRCB Prcb = KeGetCurrentPrcb();
  695. CPU_INFO CpuInfo;
  696. ULONG Temp;
  697. //
  698. // Get the CPU vendor string.
  699. //
  700. KiCpuId(0, &CpuInfo);
  701. //
  702. // Copy vendor string to PRCB.
  703. //
  704. Temp = CpuInfo.Ecx;
  705. CpuInfo.Ecx = CpuInfo.Edx;
  706. CpuInfo.Edx = Temp;
  707. RtlCopyMemory(Prcb->VendorString,
  708. &CpuInfo.Ebx,
  709. sizeof(Prcb->VendorString) - 1);
  710. Prcb->VendorString[sizeof(Prcb->VendorString) - 1] = '\0';
  711. return;
  712. }
  713. VOID
  714. KiSetFeatureBits (
  715. IN PKPRCB Prcb
  716. )
  717. /*++
  718. Routine Description:
  719. Set the current processor feature bits in the PRCB.
  720. Arguments:
  721. Prcb - Supplies a pointer to the current processor block.
  722. Return Value:
  723. None.
  724. --*/
  725. {
  726. CPU_INFO CpuInfo;
  727. ULONG FeatureBits;
  728. //
  729. // Get CPU feature information.
  730. //
  731. KiCpuId(1, &CpuInfo);
  732. //
  733. // Set the initial APIC ID.
  734. //
  735. Prcb->InitialApicId = (UCHAR)(CpuInfo.Ebx >> 24);
  736. //
  737. // If the required fetures are not present, then bugcheck.
  738. //
  739. if ((CpuInfo.Edx & HF_REQUIRED) != HF_REQUIRED) {
  740. KeBugCheckEx(UNSUPPORTED_PROCESSOR, CpuInfo.Edx, 0, 0, 0);
  741. }
  742. FeatureBits = KF_REQUIRED;
  743. if (CpuInfo.Edx & 0x00200000) {
  744. FeatureBits |= KF_DTS;
  745. }
  746. //
  747. // Get extended CPU feature information.
  748. //
  749. KiCpuId(0x80000000, &CpuInfo);
  750. //
  751. // Check the extended feature bits.
  752. //
  753. if (CpuInfo.Edx & 0x80000000) {
  754. FeatureBits |= KF_3DNOW;
  755. }
  756. Prcb->LogicalProcessorsPerPhysicalProcessor = 1;
  757. Prcb->FeatureBits = FeatureBits;
  758. return;
  759. }
  760. VOID
  761. KiSetProcessorType (
  762. VOID
  763. )
  764. /*++
  765. Routine Description:
  766. This function sets the current processor family and stepping in the PRCB.
  767. Arguments:
  768. None.
  769. Return Value:
  770. None.
  771. --*/
  772. {
  773. CPU_INFO CpuInfo;
  774. PKPRCB Prcb = KeGetCurrentPrcb();
  775. //
  776. // Get cpu feature information.
  777. //
  778. KiCpuId(1, &CpuInfo);
  779. //
  780. // Set processor family and stepping information.
  781. //
  782. Prcb->CpuID = TRUE;
  783. Prcb->CpuType = (CCHAR)((CpuInfo.Eax >> 8) & 0xf);
  784. Prcb->CpuStep = (USHORT)(((CpuInfo.Eax << 4) & 0xf00) | (CpuInfo.Eax & 0xf));
  785. return;
  786. }
  787. VOID
  788. KeOptimizeProcessorControlState (
  789. VOID
  790. )
  791. /*++
  792. Routine Description:
  793. This function performs no operation on AMD64.
  794. Arguments:
  795. None.
  796. Return Value:
  797. None.
  798. --*/
  799. {
  800. return;
  801. }