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.

1157 lines
28 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. allproc.c
  5. Abstract:
  6. This module allocates and initializes kernel resources required
  7. to start a new processor, and passes a complete process_state
  8. structre to the hal to obtain a new processor. This is done
  9. for every processor.
  10. Author:
  11. Ken Reneris (kenr) 22-Jan-92
  12. Environment:
  13. Kernel mode only.
  14. Phase 1 of bootup
  15. Revision History:
  16. --*/
  17. #include "ki.h"
  18. #ifdef NT_UP
  19. VOID
  20. KeStartAllProcessors (
  21. VOID
  22. )
  23. {
  24. // UP Build - this function is a nop
  25. }
  26. #else
  27. static VOID
  28. KiCloneDescriptor (
  29. IN PKDESCRIPTOR pSrcDescriptorInfo,
  30. IN PKDESCRIPTOR pDestDescriptorInfo,
  31. IN PVOID Base
  32. );
  33. static VOID
  34. KiCloneSelector (
  35. IN ULONG SrcSelector,
  36. IN PKGDTENTRY pNGDT,
  37. IN PKDESCRIPTOR pDestDescriptor,
  38. IN PVOID Base
  39. );
  40. VOID
  41. KiAdjustSimultaneousMultiThreadingCharacteristics(
  42. VOID
  43. );
  44. VOID
  45. KiProcessorStart(
  46. VOID
  47. );
  48. BOOLEAN
  49. KiStartWaitAcknowledge(
  50. VOID
  51. );
  52. #if defined(KE_MULTINODE)
  53. NTSTATUS
  54. KiNotNumaQueryProcessorNode(
  55. IN ULONG ProcessorNumber,
  56. OUT PUSHORT Identifier,
  57. OUT PUCHAR Node
  58. );
  59. #ifdef ALLOC_PRAGMA
  60. #pragma alloc_text(INIT, KiNotNumaQueryProcessorNode)
  61. #endif
  62. #endif
  63. #ifdef ALLOC_PRAGMA
  64. #pragma alloc_text(INIT,KeStartAllProcessors)
  65. #pragma alloc_text(INIT,KiCloneDescriptor)
  66. #pragma alloc_text(INIT,KiCloneSelector)
  67. #pragma alloc_text(INIT,KiAllProcessorsStarted)
  68. #pragma alloc_text(INIT,KiAdjustSimultaneousMultiThreadingCharacteristics)
  69. #pragma alloc_text(INIT,KiStartWaitAcknowledge)
  70. #endif
  71. enum {
  72. KcStartContinue,
  73. KcStartWait,
  74. KcStartGetId,
  75. KcStartDoNotStart,
  76. KcStartCommandError = 0xff
  77. } KiProcessorStartControl = KcStartContinue;
  78. ULONG KiProcessorStartData[4];
  79. ULONG KiBarrierWait = 0;
  80. //
  81. // KeNumprocSpecified is set to the number of processors specified with
  82. // /NUMPROC in OSLOADOPTIONS. This will bypass the license increase for
  83. // logical processors limiting the total number of processors to the number
  84. // specified.
  85. //
  86. ULONG KeNumprocSpecified;
  87. #if defined(KE_MULTINODE)
  88. PHALNUMAQUERYPROCESSORNODE KiQueryProcessorNode = KiNotNumaQueryProcessorNode;
  89. //
  90. // Statically preallocate enough KNODE structures to allow MM
  91. // to allocate pages by node during system initialization. As
  92. // processors are brought online, real KNODE structures are
  93. // allocated in the appropriate memory for the node.
  94. //
  95. // This statically allocated set will be deallocated once the
  96. // system is initialized.
  97. //
  98. #ifdef ALLOC_DATA_PRAGMA
  99. #pragma data_seg("INITDATA")
  100. #endif
  101. KNODE KiNodeInit[MAXIMUM_CCNUMA_NODES];
  102. #endif
  103. #define REJECT_PROCESSOR_LIMIT 64
  104. #define ROUNDUP16(x) (((x)+15) & ~15)
  105. VOID
  106. KeStartAllProcessors (
  107. VOID
  108. )
  109. /*++
  110. Routine Description:
  111. Called by p0 during phase 1 of bootup. This function implements
  112. the x86 specific code to contact the hal for each system processor.
  113. Arguments:
  114. Return Value:
  115. All available processors are sent to KiSystemStartup.
  116. --*/
  117. {
  118. KPROCESSOR_STATE ProcessorState;
  119. KDESCRIPTOR Descriptor;
  120. KDESCRIPTOR TSSDesc, DFTSSDesc, NMITSSDesc, PCRDesc;
  121. PKGDTENTRY pGDT;
  122. PVOID pStack;
  123. PVOID pDpcStack;
  124. ULONG DFStack;
  125. PUCHAR pThreadObject;
  126. PULONG pTopOfStack;
  127. ULONG NewProcessorNumber;
  128. BOOLEAN NewProcessor;
  129. PKPROCESS Process;
  130. PKTHREAD Thread;
  131. PKTSS pTSS;
  132. PLIST_ENTRY NextEntry;
  133. LONG NumberProcessors;
  134. SIZE_T ProcessorDataSize;
  135. UCHAR NodeNumber = 0;
  136. USHORT ProcessorId;
  137. PVOID PerProcessorAllocation;
  138. PUCHAR Base;
  139. ULONG IdtOffset;
  140. ULONG GdtOffset;
  141. NTSTATUS Status;
  142. PKNODE Node;
  143. BOOLEAN NewLicense;
  144. UCHAR RejectedProcessorCount = 0;
  145. PKPRCB NewPrcb;
  146. #if defined(KE_MULTINODE)
  147. //
  148. // In the unlikely event that processor 0 is not on node
  149. // 0, fix it.
  150. //
  151. if (KeNumberNodes > 1) {
  152. Status = KiQueryProcessorNode(0,
  153. &ProcessorId,
  154. &NodeNumber);
  155. if (NT_SUCCESS(Status)) {
  156. //
  157. // This should never fail.
  158. //
  159. if (NodeNumber != 0) {
  160. KeNodeBlock[0]->ProcessorMask &= ~1;
  161. KeNodeBlock[NodeNumber]->ProcessorMask |= 1;
  162. KeGetCurrentPrcb()->ParentNode = KeNodeBlock[NodeNumber];
  163. }
  164. }
  165. }
  166. #endif
  167. //
  168. // Calculate the size of the per processor data. This includes
  169. // PCR (+PRCB)
  170. // TSS
  171. // Idle Thread Object
  172. // NMI TSS
  173. // Double Fault TSS
  174. // Double Fault Stack
  175. // GDT
  176. // IDT
  177. //
  178. // If this is a multinode system, the KNODE structure is allocated
  179. // as well. It isn't very big so we waste a few bytes for
  180. // processors that aren't the first in a node.
  181. //
  182. // A DPC and Idle stack are also allocated but these are done
  183. // seperately.
  184. //
  185. ProcessorDataSize = ROUNDUP16(sizeof(KPCR)) +
  186. ROUNDUP16(sizeof(KTSS)) +
  187. ROUNDUP16(sizeof(ETHREAD)) +
  188. ROUNDUP16(FIELD_OFFSET(KTSS, IoMaps)) +
  189. ROUNDUP16(FIELD_OFFSET(KTSS, IoMaps)) +
  190. ROUNDUP16(DOUBLE_FAULT_STACK_SIZE);
  191. #if defined(KE_MULTINODE)
  192. ProcessorDataSize += ROUNDUP16(sizeof(KNODE));
  193. #endif
  194. //
  195. // Add sizeof GDT
  196. //
  197. GdtOffset = ProcessorDataSize;
  198. _asm {
  199. sgdt Descriptor.Limit
  200. }
  201. ProcessorDataSize += Descriptor.Limit + 1;
  202. //
  203. // Add sizeof IDT
  204. //
  205. IdtOffset = ProcessorDataSize;
  206. _asm {
  207. sidt Descriptor.Limit
  208. }
  209. ProcessorDataSize += Descriptor.Limit + 1;
  210. //
  211. // If the registered number of processors is greater than the maximum
  212. // number of processors supported, then only allow the maximum number
  213. // of supported processors.
  214. //
  215. if (KeRegisteredProcessors > MAXIMUM_PROCESSORS) {
  216. KeRegisteredProcessors = MAXIMUM_PROCESSORS;
  217. }
  218. //
  219. // Set barrier that will prevent any other processor from entering the
  220. // idle loop until all processors have been started.
  221. //
  222. KiBarrierWait = 1;
  223. //
  224. // Loop asking the HAL for the next processor. Stop when the
  225. // HAL says there aren't any more.
  226. //
  227. for (NewProcessorNumber = 1;
  228. NewProcessorNumber < MAXIMUM_PROCESSORS;
  229. NewProcessorNumber++) {
  230. if ((KeFeatureBits & KF_SMT) == 0) {
  231. //
  232. // If all the processors in the system support Simultaneous
  233. // Multi-Threading we allow the additional logical processors
  234. // in a set to run under the same license as the first logical
  235. // processor in a set.
  236. //
  237. // Otherwise, do not attempt to start more processors than
  238. // there are licenses for. (This is because as of Whistler
  239. // Beta2 we are having problems with systems that send SMIs
  240. // to processors that are not in "wait for SIPI" state. The
  241. // code to scan for additional logical processors causes
  242. // processors not licensed to be in a halted state).
  243. //
  244. // PeterJ 03/02/01.
  245. //
  246. if (NewProcessorNumber >= KeRegisteredProcessors) {
  247. break;
  248. }
  249. }
  250. #if defined(KE_MULTINODE)
  251. Status = KiQueryProcessorNode(NewProcessorNumber,
  252. &ProcessorId,
  253. &NodeNumber);
  254. if (!NT_SUCCESS(Status)) {
  255. //
  256. // No such processor, advance to next.
  257. //
  258. continue;
  259. }
  260. Node = KeNodeBlock[NodeNumber];
  261. #endif
  262. //
  263. // Allocate memory for the new processor specific data. If
  264. // the allocation fails, stop starting processors.
  265. //
  266. PerProcessorAllocation =
  267. MmAllocateIndependentPages (ProcessorDataSize, NodeNumber);
  268. if (PerProcessorAllocation == NULL) {
  269. break;
  270. }
  271. Base = (PUCHAR)PerProcessorAllocation;
  272. //
  273. // Build up a processor state for new processor
  274. //
  275. RtlZeroMemory ((PVOID) &ProcessorState, sizeof ProcessorState);
  276. //
  277. // Give the new processor its own GDT
  278. //
  279. _asm {
  280. sgdt Descriptor.Limit
  281. }
  282. KiCloneDescriptor (&Descriptor,
  283. &ProcessorState.SpecialRegisters.Gdtr,
  284. Base + GdtOffset);
  285. pGDT = (PKGDTENTRY) ProcessorState.SpecialRegisters.Gdtr.Base;
  286. //
  287. // Give new processor its own IDT
  288. //
  289. _asm {
  290. sidt Descriptor.Limit
  291. }
  292. KiCloneDescriptor (&Descriptor,
  293. &ProcessorState.SpecialRegisters.Idtr,
  294. Base + IdtOffset);
  295. //
  296. // Give new processor its own TSS and PCR
  297. //
  298. KiCloneSelector (KGDT_R0_PCR, pGDT, &PCRDesc, Base);
  299. RtlZeroMemory (Base, ROUNDUP16(sizeof(KPCR)));
  300. Base += ROUNDUP16(sizeof(KPCR));
  301. KiCloneSelector (KGDT_TSS, pGDT, &TSSDesc, Base);
  302. Base += ROUNDUP16(sizeof(KTSS));
  303. //
  304. // Idle Thread thread object.
  305. //
  306. pThreadObject = Base;
  307. RtlZeroMemory(Base, sizeof(ETHREAD));
  308. Base += ROUNDUP16(sizeof(ETHREAD));
  309. //
  310. // NMI TSS and double-fault TSS & stack.
  311. //
  312. KiCloneSelector (KGDT_DF_TSS, pGDT, &DFTSSDesc, Base);
  313. Base += ROUNDUP16(FIELD_OFFSET(KTSS, IoMaps));
  314. KiCloneSelector (KGDT_NMI_TSS, pGDT, &NMITSSDesc, Base);
  315. Base += ROUNDUP16(FIELD_OFFSET(KTSS, IoMaps));
  316. Base += DOUBLE_FAULT_STACK_SIZE;
  317. pTSS = (PKTSS)DFTSSDesc.Base;
  318. pTSS->Esp0 = (ULONG)Base;
  319. pTSS->Esp = (ULONG)Base;
  320. pTSS = (PKTSS)NMITSSDesc.Base;
  321. pTSS->Esp0 = (ULONG)Base;
  322. pTSS->Esp = (ULONG)Base;
  323. //
  324. // Set other SpecialRegisters in processor state
  325. //
  326. _asm {
  327. mov eax, cr0
  328. and eax, NOT (CR0_AM or CR0_WP)
  329. mov ProcessorState.SpecialRegisters.Cr0, eax
  330. mov eax, cr3
  331. mov ProcessorState.SpecialRegisters.Cr3, eax
  332. pushfd
  333. pop eax
  334. mov ProcessorState.ContextFrame.EFlags, eax
  335. and ProcessorState.ContextFrame.EFlags, NOT EFLAGS_INTERRUPT_MASK
  336. }
  337. ProcessorState.SpecialRegisters.Tr = KGDT_TSS;
  338. pGDT[KGDT_TSS>>3].HighWord.Bytes.Flags1 = 0x89;
  339. #if defined(_X86PAE_)
  340. ProcessorState.SpecialRegisters.Cr4 = CR4_PAE;
  341. #endif
  342. //
  343. // Allocate a DPC stack, idle thread stack and ThreadObject for
  344. // the new processor.
  345. //
  346. pStack = MmCreateKernelStack (FALSE, NodeNumber);
  347. pDpcStack = MmCreateKernelStack (FALSE, NodeNumber);
  348. //
  349. // Setup context
  350. // Push variables onto new stack
  351. //
  352. pTopOfStack = (PULONG) pStack;
  353. pTopOfStack[-1] = (ULONG) KeLoaderBlock;
  354. ProcessorState.ContextFrame.Esp = (ULONG) (pTopOfStack-2);
  355. ProcessorState.ContextFrame.Eip = (ULONG) KiSystemStartup;
  356. ProcessorState.ContextFrame.SegCs = KGDT_R0_CODE;
  357. ProcessorState.ContextFrame.SegDs = KGDT_R3_DATA;
  358. ProcessorState.ContextFrame.SegEs = KGDT_R3_DATA;
  359. ProcessorState.ContextFrame.SegFs = KGDT_R0_PCR;
  360. ProcessorState.ContextFrame.SegSs = KGDT_R0_DATA;
  361. //
  362. // Initialize new processor's PCR & Prcb
  363. //
  364. KiInitializePcr (
  365. (ULONG) NewProcessorNumber,
  366. (PKPCR) PCRDesc.Base,
  367. (PKIDTENTRY) ProcessorState.SpecialRegisters.Idtr.Base,
  368. (PKGDTENTRY) ProcessorState.SpecialRegisters.Gdtr.Base,
  369. (PKTSS) TSSDesc.Base,
  370. (PKTHREAD) pThreadObject,
  371. (PVOID) pDpcStack
  372. );
  373. NewPrcb = ((PKPCR)(PCRDesc.Base))->Prcb;
  374. //
  375. // Assume new processor will be the first processor in its
  376. // SMT set. (Right choice for non SMT processors, adjusted
  377. // later if not correct).
  378. //
  379. NewPrcb->MultiThreadSetMaster = NewPrcb;
  380. #if defined(KE_MULTINODE)
  381. //
  382. // If this is the first processor on this node, use the
  383. // space allocated for KNODE as the KNODE.
  384. //
  385. if (KeNodeBlock[NodeNumber] == &KiNodeInit[NodeNumber]) {
  386. Node = (PKNODE)Base;
  387. *Node = KiNodeInit[NodeNumber];
  388. KeNodeBlock[NodeNumber] = Node;
  389. }
  390. Base += ROUNDUP16(sizeof(KNODE));
  391. NewPrcb->ParentNode = Node;
  392. #else
  393. NewPrcb->ParentNode = KeNodeBlock[0];
  394. #endif
  395. ASSERT(((PUCHAR)PerProcessorAllocation + GdtOffset) == Base);
  396. //
  397. // Adjust LoaderBlock so it has the next processors state
  398. //
  399. KeLoaderBlock->KernelStack = (ULONG) pTopOfStack;
  400. KeLoaderBlock->Thread = (ULONG) pThreadObject;
  401. KeLoaderBlock->Prcb = (ULONG) NewPrcb;
  402. RetryStartProcessor:
  403. //
  404. // Get CPUID(1) info from the starting processor.
  405. //
  406. KiProcessorStartData[0] = 1;
  407. KiProcessorStartControl = KcStartGetId;
  408. //
  409. // Contact hal to start new processor
  410. //
  411. NewProcessor = HalStartNextProcessor (KeLoaderBlock, &ProcessorState);
  412. if (!NewProcessor) {
  413. //
  414. // There wasn't another processor, so free resources and
  415. // break
  416. //
  417. KiProcessorBlock[NewProcessorNumber] = NULL;
  418. MmFreeIndependentPages ( PerProcessorAllocation, ProcessorDataSize);
  419. MmDeleteKernelStack ( pStack, FALSE);
  420. MmDeleteKernelStack ( pDpcStack, FALSE);
  421. break;
  422. }
  423. //
  424. // Wait for the new processor to fill in the CPUID data requested.
  425. //
  426. NewLicense = TRUE;
  427. if (KiStartWaitAcknowledge() == TRUE) {
  428. if (KiProcessorStartData[3] & 0x10000000) {
  429. //
  430. // This processor might support SMT, in which case, if this
  431. // is not the first logical processor in an SMT set, it should
  432. // not be charged a license. If it is the first in a set,
  433. // and the total number of sets exceeds the number of licensed
  434. // processors, this processor should not be allowed to start.
  435. //
  436. ULONG ApicMask;
  437. ULONG ApicId;
  438. ULONG i;
  439. PKPRCB SmtCheckPrcb;
  440. //
  441. // Round number of logical processors per physical processor
  442. // up to a power of two then subrtact 1 to get the logical
  443. // processor apic mask.
  444. //
  445. ApicMask = (KiProcessorStartData[1] >> 16) & 0xff;
  446. ApicMask = ApicMask + ApicMask - 1;
  447. KeFindFirstSetLeftMember(ApicMask, &ApicMask);
  448. ApicMask = ~((1 << ApicMask) - 1);
  449. ApicId = (KiProcessorStartData[1] >> 24) & ApicMask;
  450. //
  451. // Check to see if any started processor is in the same
  452. // set.
  453. //
  454. for (i = 0; i < NewProcessorNumber; i++) {
  455. SmtCheckPrcb = KiProcessorBlock[i];
  456. if (SmtCheckPrcb) {
  457. if ((SmtCheckPrcb->InitialApicId & ApicMask) == ApicId) {
  458. NewLicense = FALSE;
  459. NewPrcb->MultiThreadSetMaster = SmtCheckPrcb;
  460. break;
  461. }
  462. }
  463. }
  464. }
  465. }
  466. if ((NewLicense == FALSE) &&
  467. ((KeNumprocSpecified == 0) ||
  468. (KeRegisteredProcessors < KeNumprocSpecified))) {
  469. //
  470. // This processor is a logical processor in the same SMT
  471. // set as another logical processor. Don't charge a
  472. // license for it.
  473. //
  474. KeRegisteredProcessors++;
  475. } else {
  476. //
  477. // The new processor is the first or only logical processor
  478. // in a physical processor. If the number of physical
  479. // processors exceeds the license, don't start this processor.
  480. //
  481. if ((ULONG)KeNumberProcessors >= KeRegisteredProcessors) {
  482. KiProcessorStartControl = KcStartDoNotStart;
  483. KiStartWaitAcknowledge();
  484. if (++RejectedProcessorCount > REJECT_PROCESSOR_LIMIT) {
  485. //
  486. // The HAL must not be advancing to the next
  487. // processor. Give up.
  488. //
  489. // Note: This test is due to the introduction
  490. // of this feature of asking the HAL for a new
  491. // processor (using the same processor number
  492. // as the just rejected processor). If the
  493. // HAL does not support advancing under this
  494. // condition we would loop here forever.
  495. //
  496. break;
  497. }
  498. //
  499. // The new processor has now returned to the state it
  500. // was in before the HAL initialized it. Have the
  501. // HAL start the next processor using the same resource
  502. // set.
  503. //
  504. goto RetryStartProcessor;
  505. }
  506. }
  507. KiProcessorStartControl = KcStartContinue;
  508. #if defined(KE_MULTINODE)
  509. Node->ProcessorMask |= 1 << NewProcessorNumber;
  510. #endif
  511. //
  512. // Wait for processor to initialize in kernel, then loop for another
  513. //
  514. while (*((volatile ULONG *) &KeLoaderBlock->Prcb) != 0) {
  515. KeYieldProcessor();
  516. }
  517. }
  518. //
  519. // All processors have been stated.
  520. //
  521. KiAllProcessorsStarted();
  522. //
  523. // Reset and synchronize the performance counters of all processors, by
  524. // applying a null adjustment to the interrupt time
  525. //
  526. KiAdjustInterruptTime (0);
  527. //
  528. // Allow all processors that were started to enter the idle loop and
  529. // begin execution.
  530. //
  531. KiBarrierWait = 0;
  532. }
  533. static VOID
  534. KiCloneSelector (
  535. IN ULONG SrcSelector,
  536. IN PKGDTENTRY pNGDT,
  537. IN PKDESCRIPTOR pDestDescriptor,
  538. IN PVOID Base
  539. )
  540. /*++
  541. Routine Description:
  542. Makes a copy of the current selector's data, and updates the new
  543. gdt's linear address to point to the new copy.
  544. Arguments:
  545. SrcSelector - Selector value to clone
  546. pNGDT - New gdt table which is being built
  547. DescDescriptor - descriptor structure to fill in with resulting memory
  548. Base - Base memory for the new descriptor.
  549. Return Value:
  550. None.
  551. --*/
  552. {
  553. KDESCRIPTOR Descriptor;
  554. PKGDTENTRY pGDT;
  555. ULONG CurrentBase;
  556. ULONG NewBase;
  557. _asm {
  558. sgdt fword ptr [Descriptor.Limit] ; Get GDT's addr
  559. }
  560. pGDT = (PKGDTENTRY) Descriptor.Base;
  561. pGDT += SrcSelector >> 3;
  562. pNGDT += SrcSelector >> 3;
  563. CurrentBase = pGDT->BaseLow | (pGDT->HighWord.Bits.BaseMid << 16) |
  564. (pGDT->HighWord.Bits.BaseHi << 24);
  565. Descriptor.Base = CurrentBase;
  566. Descriptor.Limit = pGDT->LimitLow;
  567. if (pGDT->HighWord.Bits.Granularity & GRAN_PAGE)
  568. Descriptor.Limit = (Descriptor.Limit << PAGE_SHIFT) -1;
  569. KiCloneDescriptor (&Descriptor, pDestDescriptor, Base);
  570. NewBase = pDestDescriptor->Base;
  571. pNGDT->BaseLow = (USHORT) NewBase & 0xffff;
  572. pNGDT->HighWord.Bits.BaseMid = (UCHAR) (NewBase >> 16) & 0xff;
  573. pNGDT->HighWord.Bits.BaseHi = (UCHAR) (NewBase >> 24) & 0xff;
  574. }
  575. static VOID
  576. KiCloneDescriptor (
  577. IN PKDESCRIPTOR pSrcDescriptor,
  578. IN PKDESCRIPTOR pDestDescriptor,
  579. IN PVOID Base
  580. )
  581. /*++
  582. Routine Description:
  583. Makes a copy of the specified descriptor, and supplies a return
  584. descriptor for the new copy
  585. Arguments:
  586. pSrcDescriptor - descriptor to clone
  587. pDescDescriptor - the cloned descriptor
  588. Base - Base memory for the new descriptor.
  589. Return Value:
  590. None.
  591. --*/
  592. {
  593. ULONG Size;
  594. Size = pSrcDescriptor->Limit + 1;
  595. pDestDescriptor->Limit = (USHORT) Size -1;
  596. pDestDescriptor->Base = (ULONG) Base;
  597. RtlCopyMemory(Base, (PVOID)pSrcDescriptor->Base, Size);
  598. }
  599. VOID
  600. KiAdjustSimultaneousMultiThreadingCharacteristics(
  601. VOID
  602. )
  603. /*++
  604. Routine Description:
  605. This routine is called (possibly while the dispatcher lock is held)
  606. after processors are added to or removed from the system. It runs
  607. thru the PRCBs for each processor in the system and adjusts scheduling
  608. data.
  609. Arguments:
  610. None.
  611. Return Value:
  612. None.
  613. --*/
  614. {
  615. ULONG ProcessorNumber;
  616. ULONG BuddyNumber;
  617. KAFFINITY ProcessorSet;
  618. PKPRCB Prcb;
  619. PKPRCB BuddyPrcb;
  620. ULONG ApicMask;
  621. ULONG ApicId;
  622. ULONG NextIndependent;
  623. if ((KeFeatureBits & KF_SMT) == 0) {
  624. //
  625. // Nobody doing SMT, nothing to do.
  626. //
  627. return;
  628. }
  629. for (ProcessorNumber = 0;
  630. ProcessorNumber < (ULONG)KeNumberProcessors;
  631. ProcessorNumber++) {
  632. Prcb = KiProcessorBlock[ProcessorNumber];
  633. //
  634. // Skip processors which are not present or which do not
  635. // support Simultaneous Multi Threading.
  636. //
  637. if ((Prcb == NULL) || ((Prcb->FeatureBits & KF_SMT) == 0)) {
  638. continue;
  639. }
  640. NextIndependent = 0;
  641. //
  642. // Find all processors with the same physical processor APIC ID.
  643. // The APIC ID for the physical processor is the upper portion
  644. // of the APIC ID, the number of bits in the lower portion is
  645. // log 2 (number logical processors per physical rounded up to
  646. // a power of 2).
  647. //
  648. ASSERT(Prcb->LogicalProcessorsPerPhysicalProcessor);
  649. ApicId = Prcb->InitialApicId;
  650. ApicMask = Prcb->LogicalProcessorsPerPhysicalProcessor;
  651. if (ApicMask == 0) {
  652. //
  653. // Sanity fails: This processor isn't right.
  654. //
  655. continue;
  656. }
  657. //
  658. // Round number of logical processors up to a power of 2
  659. // then subtract one to get the logical processor apic mask.
  660. //
  661. ApicMask = ApicMask + ApicMask - 1;
  662. KeFindFirstSetLeftMember(ApicMask, &ApicMask);
  663. ApicMask = ~((1 << ApicMask) - 1);
  664. ApicId &= ApicMask;
  665. ProcessorSet = 1 << Prcb->Number;
  666. //
  667. // Examine each remaining processor to see if it is part of
  668. // the same set.
  669. //
  670. for (BuddyNumber = ProcessorNumber + 1;
  671. BuddyNumber < (ULONG)KeNumberProcessors;
  672. BuddyNumber++) {
  673. BuddyPrcb = KiProcessorBlock[BuddyNumber];
  674. //
  675. // Skip not present, not SMT.
  676. //
  677. if ((BuddyPrcb == NULL) ||
  678. ((BuddyPrcb->FeatureBits & KF_SMT) == 0)) {
  679. continue;
  680. }
  681. //
  682. // Does this processor have the same ID as the one
  683. // we're looking for?
  684. //
  685. if ((BuddyPrcb->InitialApicId & ApicMask) != ApicId) {
  686. //
  687. // No, if this is the first occurance on another
  688. // APIC Id (relative to the processor we're examining)
  689. // then remember this processor as it's the next
  690. // independent processor.
  691. //
  692. if (!NextIndependent) {
  693. NextIndependent = BuddyNumber;
  694. }
  695. continue;
  696. }
  697. //
  698. // Match.
  699. //
  700. ASSERT(Prcb->LogicalProcessorsPerPhysicalProcessor ==
  701. BuddyPrcb->LogicalProcessorsPerPhysicalProcessor);
  702. ProcessorSet |= 1 << BuddyPrcb->Number;
  703. BuddyPrcb->MultiThreadProcessorSet |= ProcessorSet;
  704. }
  705. Prcb->MultiThreadProcessorSet |= ProcessorSet;
  706. }
  707. }
  708. VOID
  709. KiAllProcessorsStarted(
  710. VOID
  711. )
  712. /*++
  713. Routine Description:
  714. This routine is called once all processors in the system
  715. have been started.
  716. Arguments:
  717. None.
  718. Return Value:
  719. None.
  720. --*/
  721. {
  722. ULONG i;
  723. //
  724. // If the system contains Simultaneous Multi Threaded processors,
  725. // adjust grouping information now that each processor is started.
  726. //
  727. KiAdjustSimultaneousMultiThreadingCharacteristics();
  728. #if defined(KE_MULTINODE)
  729. //
  730. // Make sure there are no references to the temporary nodes
  731. // used during initialization.
  732. //
  733. for (i = 0; i < KeNumberNodes; i++) {
  734. if (KeNodeBlock[i] == &KiNodeInit[i]) {
  735. //
  736. // No processor started on this node so no new node
  737. // structure has been allocated. This is possible
  738. // if the node contains only memory or IO busses. At
  739. // this time we need to allocate a permanent node
  740. // structure for the node.
  741. //
  742. KeNodeBlock[i] = ExAllocatePoolWithTag(NonPagedPool,
  743. sizeof(KNODE),
  744. ' eK');
  745. if (KeNodeBlock[i]) {
  746. *KeNodeBlock[i] = KiNodeInit[i];
  747. }
  748. }
  749. }
  750. for (i = KeNumberNodes; i < MAXIMUM_CCNUMA_NODES; i++) {
  751. KeNodeBlock[i] = NULL;
  752. }
  753. #endif
  754. if (KeNumberNodes == 1) {
  755. //
  756. // For Non NUMA machines, Node 0 gets all processors.
  757. //
  758. KeNodeBlock[0]->ProcessorMask = KeActiveProcessors;
  759. }
  760. }
  761. #if defined(KE_MULTINODE)
  762. NTSTATUS
  763. KiNotNumaQueryProcessorNode(
  764. IN ULONG ProcessorNumber,
  765. OUT PUSHORT Identifier,
  766. OUT PUCHAR Node
  767. )
  768. /*++
  769. Routine Description:
  770. This routine is a stub used on non NUMA systems to provide a
  771. consistent method of determining the NUMA configuration rather
  772. than checking for the presense of multiple nodes inline.
  773. Arguments:
  774. ProcessorNumber supplies the system logical processor number.
  775. Identifier supplies the address of a variable to receive
  776. the unique identifier for this processor.
  777. NodeNumber supplies the address of a variable to receive
  778. the number of the node this processor resides on.
  779. Return Value:
  780. Returns success.
  781. --*/
  782. {
  783. *Identifier = (USHORT)ProcessorNumber;
  784. *Node = 0;
  785. return STATUS_SUCCESS;
  786. }
  787. #endif
  788. VOID
  789. KiProcessorStart(
  790. VOID
  791. )
  792. /*++
  793. Routine Description:
  794. This routine is a called when a processor begins execution.
  795. It is used to pass processor characteristic information to
  796. the boot processor and to control the starting or non-starting
  797. of this processor.
  798. Arguments:
  799. None.
  800. Return Value:
  801. None.
  802. --*/
  803. {
  804. while (TRUE) {
  805. switch (KiProcessorStartControl) {
  806. case KcStartContinue:
  807. return;
  808. case KcStartWait:
  809. KeYieldProcessor();
  810. break;
  811. case KcStartGetId:
  812. CPUID(KiProcessorStartData[0],
  813. &KiProcessorStartData[0],
  814. &KiProcessorStartData[1],
  815. &KiProcessorStartData[2],
  816. &KiProcessorStartData[3]);
  817. KiProcessorStartControl = KcStartWait;
  818. break;
  819. case KcStartDoNotStart:
  820. //
  821. // The boot processor has determined that this processor
  822. // should NOT be started.
  823. //
  824. // Acknowledge the command so the boot processor will
  825. // continue, disable interrupts (should already be
  826. // the case here) and HALT the processor.
  827. //
  828. KiProcessorStartControl = KcStartWait;
  829. _disable();
  830. while(1) {
  831. _asm { hlt };
  832. }
  833. default:
  834. //
  835. // Not much we can do with unknown commands.
  836. //
  837. KiProcessorStartControl = KcStartCommandError;
  838. break;
  839. }
  840. }
  841. }
  842. BOOLEAN
  843. KiStartWaitAcknowledge(
  844. VOID
  845. )
  846. {
  847. while (KiProcessorStartControl != KcStartWait) {
  848. if (KiProcessorStartControl == KcStartCommandError) {
  849. return FALSE;
  850. }
  851. KeYieldProcessor();
  852. }
  853. return TRUE;
  854. }
  855. #endif // !NT_UP